Commit f9de9623 by Bridger Maxwell

Merge remote-tracking branch 'origin/master' into course_start

parents 60da2304 214d03c1
......@@ -9,8 +9,11 @@ def replace(static_url, prefix=None):
prefix = prefix + '/'
quote = static_url.group('quote')
url = staticfiles_storage.url(prefix + static_url.group('rest'))
return "".join([quote, url, quote])
if staticfiles_storage.exists(static_url.group('rest')):
return static_url.group(0)
else:
url = staticfiles_storage.url(prefix + static_url.group('rest'))
return "".join([quote, url, quote])
def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/'):
......@@ -18,9 +21,9 @@ def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/'):
return replace(static_url, staticfiles_prefix)
return re.sub(r"""
(?x) # flags=re.VERBOSE
(?P<quote>\\?['"]) # the opening quotes
{prefix} # the prefix
(?P<rest>.*?) # everything else in the url
(?P=quote) # the first matching closing quote
(?x) # flags=re.VERBOSE
(?P<quote>\\?['"]) # the opening quotes
(?P<prefix>{prefix}) # the prefix
(?P<rest>.*?) # everything else in the url
(?P=quote) # the first matching closing quote
""".format(prefix=replace_prefix), replace_url, text)
......@@ -172,12 +172,8 @@ class XmlDescriptor(XModuleDescriptor):
log.debug('filepath=%s, resources_fs=%s' % (filepath, system.resources_fs))
try:
with system.resources_fs.open(filepath) as file:
try:
definition_xml = cls.file_to_xml(file)
except:
log.exception("Failed to parse xml in file %s" % filepath)
raise
except ResourceNotFoundError:
definition_xml = cls.file_to_xml(file)
except (ResourceNotFoundError, etree.XMLSyntaxError):
log.exception('Unable to load file contents at path %s' % filepath)
return {'data': 'Error loading file contents at path %s' % filepath}
......
import json
import logging
import settings
import uuid
from django.conf import settings
......@@ -13,8 +12,9 @@ import courseware.grades as grades
from certificates.models import GeneratedCertificate, certificate_state_for_student, revoke_certificate
from mitxmako.shortcuts import render_to_response, render_to_string
from student.models import UserProfile
from student.survey_questions import exit_survey_list_for_student
from student.views import student_took_survey, record_exit_survey
#TODO: Finish migrating these changes from stable
# from student.survey_questions import exit_survey_list_for_student
# from student.views import student_took_survey, record_exit_survey
log = logging.getLogger("mitx.certificates")
......
import os
from django.contrib.auth.decorators import login_required
from django.core.servers.basehttp import FileWrapper
from django.db.models.fields.files import FieldFile
from django.http import HttpResponse, HttpResponseForbidden, Http404
from django.template import loader, Context
from models import ArticleAttachment, get_attachment_filepath
from views import check_permissions, fetch_from_url
from wiki_settings import (
WIKI_ALLOW_ANON_ATTACHMENTS,
WIKI_ALLOW_ATTACHMENTS,
WIKI_ATTACHMENTS_MAX,
WIKI_ATTACHMENTS_ROOT,
WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS,
WIKI_REQUIRE_LOGIN_VIEW,
WIKI_REQUIRE_LOGIN_EDIT,
)
def add_attachment(request, wiki_url):
(article, path, err) = fetch_from_url(request, wiki_url)
if err:
return err
perm_err = check_permissions(request, article, check_write=True, check_locked=True)
if perm_err:
return perm_err
if not WIKI_ALLOW_ATTACHMENTS or (not WIKI_ALLOW_ANON_ATTACHMENTS and request.user.is_anonymous()):
return HttpResponseForbidden()
if request.method == 'POST':
if request.FILES.__contains__('attachment'):
attachment = ArticleAttachment()
if not request.user.is_anonymous():
attachment.uploaded_by = request.user
attachment.article = article
file = request.FILES['attachment']
file_rel_path = get_attachment_filepath(attachment, file.name)
chunk_size = request.upload_handlers[0].chunk_size
filefield = FieldFile(attachment, attachment.file, file_rel_path)
attachment.file = filefield
file_path = WIKI_ATTACHMENTS_ROOT + attachment.file.name
if not request.POST.__contains__('overwrite') and os.path.exists(file_path):
c = Context({'overwrite_warning' : True,
'wiki_article': article,
'filename': file.name})
t = loader.get_template('simplewiki_updateprogressbar.html')
return HttpResponse(t.render(c))
if file.size > WIKI_ATTACHMENTS_MAX:
c = Context({'too_big' : True,
'max_size': WIKI_ATTACHMENTS_MAX,
'wiki_article': article,
'file': file})
t = loader.get_template('simplewiki_updateprogressbar.html')
return HttpResponse(t.render(c))
def get_extension(fname):
return attachment.file.name.split('.')[-2]
if WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS and not \
get_extension(attachment.file.name) in WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS:
c = Context({'extension_err' : True,
'extensions': WIKI_ATTACHMENTS_ALLOWED_EXTENSIONS,
'wiki_article': article,
'file': file})
t = loader.get_template('simplewiki_updateprogressbar.html')
return HttpResponse(t.render(c))
# Remove existing attachments
# TODO: Move this until AFTER having removed file.
# Current problem is that Django's FileField delete() method
# automatically deletes files
for a in article.attachments():
if file_rel_path == a.file.name:
a.delete()
def receive_file():
destination = open(file_path, 'wb+')
size = file.size
cnt = 0
c = Context({'started' : True,})
t = loader.get_template('simplewiki_updateprogressbar.html')
yield t.render(c)
for chunk in file.chunks():
cnt += 1
destination.write(chunk)
c = Context({'progress_width' : (cnt*chunk_size) / size,
'wiki_article': article,})
t = loader.get_template('simplewiki_updateprogressbar.html')
yield t.render(c)
c = Context({'finished' : True,
'wiki_article': article,})
t = loader.get_template('simplewiki_updateprogressbar.html')
destination.close()
attachment.save()
yield t.render(c)
return HttpResponse(receive_file())
return HttpResponse('')
# Taken from http://www.djangosnippets.org/snippets/365/
def send_file(request, filepath):
"""
Send a file through Django without loading the whole file into
memory at once. The FileWrapper will turn the file object into an
iterator for chunks of 8KB.
"""
filename = filepath
wrapper = FileWrapper(file(filename))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Length'] = os.path.getsize(filename)
return response
def view_attachment(request, wiki_url, file_name):
(article, path, err) = fetch_from_url(request, wiki_url)
if err:
return err
perm_err = check_permissions(request, article, check_read=True)
if perm_err:
return perm_err
attachment = None
for a in article.attachments():
if get_attachment_filepath(a, file_name) == a.file.name:
attachment = a
if attachment:
filepath = WIKI_ATTACHMENTS_ROOT + attachment.file.name
if os.path.exists(filepath):
return send_file(request, filepath)
raise Http404()
####################
# LOGIN PROTECTION #
####################
if WIKI_REQUIRE_LOGIN_VIEW:
view_attachment = login_required(view_attachment)
if WIKI_REQUIRE_LOGIN_EDIT or not WIKI_ALLOW_ANON_ATTACHMENTS:
add_attachment = login_required(add_attachment)
......@@ -186,7 +186,7 @@ if os.path.isdir(DATA_DIR):
# should no longer be added to STATICFILES
(course_dir, DATA_DIR / course_dir)
for course_dir in os.listdir(DATA_DIR)
if os.path.isdir(course_dir)
if os.path.isdir(DATA_DIR / course_dir)
]
# Locale/Internationalization
......
......@@ -89,57 +89,57 @@ nav.sequence-nav {
//video
&.seq_video_inactive {
@extend .inactive;
background-image: url('../../images/sequence-nav/video-icon-normal.png');
background-image: url('../images/sequence-nav/video-icon-normal.png');
background-position: center;
}
&.seq_video_visited {
@extend .visited;
background-image: url('../../images/sequence-nav/video-icon-visited.png');
background-image: url('../images/sequence-nav/video-icon-visited.png');
background-position: center;
}
&.seq_video_active {
@extend .active;
background-image: url('../../images/sequence-nav/video-icon-current.png');
background-image: url('../images/sequence-nav/video-icon-current.png');
background-position: center;
}
//other
&.seq_other_inactive {
@extend .inactive;
background-image: url('../../images/sequence-nav/document-icon-normal.png');
background-image: url('../images/sequence-nav/document-icon-normal.png');
background-position: center;
}
&.seq_other_visited {
@extend .visited;
background-image: url('../../images/sequence-nav/document-icon-visited.png');
background-image: url('../images/sequence-nav/document-icon-visited.png');
background-position: center;
}
&.seq_other_active {
@extend .active;
background-image: url('../../images/sequence-nav/document-icon-current.png');
background-image: url('../images/sequence-nav/document-icon-current.png');
background-position: center;
}
//vertical & problems
&.seq_vertical_inactive, &.seq_problem_inactive {
@extend .inactive;
background-image: url('../../images/sequence-nav/list-icon-normal.png');
background-image: url('../images/sequence-nav/list-icon-normal.png');
background-position: center;
}
&.seq_vertical_visited, &.seq_problem_visited {
@extend .visited;
background-image: url('../../images/sequence-nav/list-icon-visited.png');
background-image: url('../images/sequence-nav/list-icon-visited.png');
background-position: center;
}
&.seq_vertical_active, &.seq_problem_active {
@extend .active;
background-image: url('../../images/sequence-nav/list-icon-current.png');
background-image: url('../images/sequence-nav/list-icon-current.png');
background-position: center;
}
......@@ -229,7 +229,7 @@ nav.sequence-nav {
&.prev {
a {
background-image: url('../../images/sequence-nav/previous-icon.png');
background-image: url('../images/sequence-nav/previous-icon.png');
&:hover {
background-color: $cream;
......@@ -239,7 +239,7 @@ nav.sequence-nav {
&.next {
a {
background-image: url('../../images/sequence-nav/next-icon.png');
background-image: url('../images/sequence-nav/next-icon.png');
&:hover {
background-color: $cream;
......@@ -310,7 +310,7 @@ section.course-content {
&.prev {
a {
background-image: url('../../images/sequence-nav/previous-icon.png');
background-image: url('../images/sequence-nav/previous-icon.png');
border-right: 1px solid darken(#f6efd4, 20%);
&:hover {
......@@ -321,7 +321,7 @@ section.course-content {
&.next {
a {
background-image: url('../../images/sequence-nav/next-icon.png');
background-image: url('../images/sequence-nav/next-icon.png');
&:hover {
background-color: none;
......
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