Commit a1088275 by Julian Arni

Route ajax request to appropriate view, and show feedback only then

Hook up view

Fix getStatus function
parent c62691e9
...@@ -18,8 +18,8 @@ from django_future.csrf import ensure_csrf_cookie ...@@ -18,8 +18,8 @@ from django_future.csrf import ensure_csrf_cookie
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.servers.basehttp import FileWrapper from django.core.servers.basehttp import FileWrapper
from django.core.files.temp import NamedTemporaryFile from django.core.files.temp import NamedTemporaryFile
from django.views.decorators.http import require_http_methods
from django.core.exceptions import SuspiciousOperation from django.core.exceptions import SuspiciousOperation
from django.views.decorators.http import require_http_methods, require_GET
from mitxmako.shortcuts import render_to_response from mitxmako.shortcuts import render_to_response
from auth.authz import create_all_course_groups from auth.authz import create_all_course_groups
...@@ -36,7 +36,7 @@ from util.json_request import JsonResponse ...@@ -36,7 +36,7 @@ from util.json_request import JsonResponse
from extract_tar import safetar_extractall from extract_tar import safetar_extractall
__all__ = ['import_course', 'generate_export_course', 'export_course'] __all__ = ['import_course', 'import_status', 'generate_export_course', 'export_course']
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -145,15 +145,15 @@ def import_course(request, org, course, name): ...@@ -145,15 +145,15 @@ def import_course(request, org, course, name):
else: # This was the last chunk. else: # This was the last chunk.
# 'Lock' with status info. # Use sessions to keep info about import progress
status_file = data_root / (course + filename + ".lock") session_status = request.session.setdefault("import_status", {})
key = org + course + filename
session_status[key] = 1
request.session.modified = True
# Do everything from now on in a with-context, to be sure we've # Do everything from now on in a try-finally block to make sure
# properly cleaned up. # everything is properly cleaned up.
with wfile(status_file, course_dir): try:
with open(status_file, 'w+') as sf:
sf.write("Extracting")
tar_file = tarfile.open(temp_filepath) tar_file = tarfile.open(temp_filepath)
try: try:
...@@ -167,8 +167,8 @@ def import_course(request, org, course, name): ...@@ -167,8 +167,8 @@ def import_course(request, org, course, name):
status=400 status=400
) )
with open(status_file, 'w+') as sf: session_status[key] = 2
sf.write("Verifying") request.session.modified = True
# find the 'course.xml' file # find the 'course.xml' file
dirpath = None dirpath = None
...@@ -221,12 +221,15 @@ def import_course(request, org, course, name): ...@@ -221,12 +221,15 @@ def import_course(request, org, course, name):
logging.debug('new course at {0}'.format(course_items[0].location)) logging.debug('new course at {0}'.format(course_items[0].location))
with open(status_file, 'w') as sf: session_status[key] = 3
sf.write("Updating course") request.session.modified = True
create_all_course_groups(request.user, course_items[0].location) create_all_course_groups(request.user, course_items[0].location)
logging.debug('created all course groups at {0}'.format(course_items[0].location)) logging.debug('created all course groups at {0}'.format(course_items[0].location))
finally:
shutil.rmtree(course_dir)
return JsonResponse({'Status': 'OK'}) return JsonResponse({'Status': 'OK'})
else: else:
course_module = modulestore().get_item(location) course_module = modulestore().get_item(location)
...@@ -240,33 +243,27 @@ def import_course(request, org, course, name): ...@@ -240,33 +243,27 @@ def import_course(request, org, course, name):
}) })
}) })
@require_GET
@ensure_csrf_cookie @ensure_csrf_cookie
@login_required @login_required
def get_import_status(request, course, filename): def import_status(request, org, course, name):
""" """
Returns an integer corresponding to the status of a file import. These are: Returns an integer corresponding to the status of a file import. These are:
0 : No status file found (import done or upload still in progress) 0 : No status info found (import done or upload still in progress)
1 : Extracting file 1 : Extracting file
2 : Validating. 2 : Validating.
3 : Importing to mongo 3 : Importing to mongo
4 : Error reading file (e.g., converting contents to int)
""" """
data_root = path(settings.GITHUB_REPO_ROOT)
status_file = data_root / (course + filename + ".lock")
if not os.path.isfile(status_file):
return JsonResponse({"ImportStatus": 0 })
with open(status_file, "r") as f:
try:
status = int(f.read())
except ValueError:
status = 4
return JsonResponse({"ImportStatus": status})
try:
session_status = request.session["import_status"]
status = session_status[org + course + name]
except KeyError:
status = 0
return JsonResponse({"ImportStatus": status })
@ensure_csrf_cookie @ensure_csrf_cookie
......
...@@ -121,6 +121,11 @@ ...@@ -121,6 +121,11 @@
} }
} }
div.status-info-block {
display: none;
text-align: left;
}
.not-started { .not-started {
opacity: 0.4; opacity: 0.4;
} }
......
...@@ -35,24 +35,18 @@ ...@@ -35,24 +35,18 @@
<input type="file" name="course-data" class="file-input" > <input type="file" name="course-data" class="file-input" >
<input type="submit" value="${_('Replace my course with the one above')}" class="submit-button" > <input type="submit" value="${_('Replace my course with the one above')}" class="submit-button" >
<input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}"> <input type="hidden" name="csrfmiddlewaretoken" value="${csrf_token}">
<div id="status-infos" class="status-infos"> <div id="status-info-block" class="status-info-block">
<p class="status-info in-progress"> <p class="status-info not-started">
<i class="icon-check-empty"></i>
Unpacking Unpacking
<span class="loading-dots">.</span>
<span class="loading-dots">.</span>
<span class="loading-dots">.</span>
</p> </p>
<p class="status-info not-started"> <p class="status-info not-started">
<i class="icon-check-empty"></i>
Verifying Verifying
<span class="loading-dots">.</span>
<span class="loading-dots">.</span>
<span class="loading-dots">.</span>
</p> </p>
<p class="status-info not-started"> <p class="status-info not-started">
<i class="icon-check-empty"></i>
Importing Importing
<span class="loading-dots">.</span>
<span class="loading-dots">.</span>
<span class="loading-dots">.</span>
</p> </p>
</div> </div>
<div class="progress-bar"> <div class="progress-bar">
...@@ -69,6 +63,7 @@ ...@@ -69,6 +63,7 @@
<script> <script>
require(["jquery", "jquery.fileupload"], function($) { require(["jquery", "jquery.fileupload"], function($) {
var file;
var bar = $('.progress-bar'); var bar = $('.progress-bar');
var fill = $('.progress-fill'); var fill = $('.progress-fill');
var percent = $('.percent'); var percent = $('.percent');
...@@ -78,6 +73,8 @@ var submitBtn = $('.submit-button'); ...@@ -78,6 +73,8 @@ var submitBtn = $('.submit-button');
var allStats = $('#status-infos'); var allStats = $('#status-infos');
var feedbackUrl = "${reverse('import_status', kwargs=dict(org=context_course.location.org, course=context_course.location.course, name='fillerName'))}"
$('#fileupload').fileupload({ $('#fileupload').fileupload({
...@@ -90,7 +87,7 @@ $('#fileupload').fileupload({ ...@@ -90,7 +87,7 @@ $('#fileupload').fileupload({
add: function(e, data) { add: function(e, data) {
submitBtn.unbind('click'); submitBtn.unbind('click');
var file = data.files[0]; file = data.files[0];
if (file.name.match(/tar\.gz$/)) { if (file.name.match(/tar\.gz$/)) {
submitBtn.click(function(e){ submitBtn.click(function(e){
e.preventDefault(); e.preventDefault();
...@@ -110,10 +107,25 @@ $('#fileupload').fileupload({ ...@@ -110,10 +107,25 @@ $('#fileupload').fileupload({
}, },
progressall: function(e, data){ progressall: function(e, data){
var percentVal = parseInt(data.loaded / data.total * 100, 10) + "%"; var doneAt;
bar.show(); var percentInt = data.loaded / data.total * 100
fill.width(percentVal); var percentVal = parseInt(percentInt, 10) + "%";
percent.html(percentVal); // Firefox makes ProgressEvent.loaded equal ProgressEvent.total only
// after receiving a response from the server (see Mozilla bug 637002),
// so for Firefox we jump the gun a little.
if (navigator.userAgent.toLowerCase().indexOf('firefox') > -1) {
doneAt = 95;
} else {
doneAt = 99;
}
if (percentInt >= doneAt) {
bar.hide();
startServerFeedback(feedbackUrl.replace("fillerName", file.name));
} else {
bar.show();
fill.width(percentVal);
percent.html(percentVal);
}
}, },
done: function(e, data){ done: function(e, data){
bar.hide(); bar.hide();
......
...@@ -29,6 +29,8 @@ urlpatterns = ('', # nopep8 ...@@ -29,6 +29,8 @@ urlpatterns = ('', # nopep8
'contentstore.views.course_index', name='course_index'), 'contentstore.views.course_index', name='course_index'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/import/(?P<name>[^/]+)$', url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/import/(?P<name>[^/]+)$',
'contentstore.views.import_course', name='import_course'), 'contentstore.views.import_course', name='import_course'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/import_status/(?P<name>[^/]+)$',
'contentstore.views.import_status', name='import_status'),
url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/export/(?P<name>[^/]+)$', url(r'^(?P<org>[^/]+)/(?P<course>[^/]+)/export/(?P<name>[^/]+)$',
'contentstore.views.export_course', name='export_course'), 'contentstore.views.export_course', name='export_course'),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment