Commit f9de9623 by Bridger Maxwell

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

parents 60da2304 214d03c1
...@@ -9,6 +9,9 @@ def replace(static_url, prefix=None): ...@@ -9,6 +9,9 @@ def replace(static_url, prefix=None):
prefix = prefix + '/' prefix = prefix + '/'
quote = static_url.group('quote') quote = static_url.group('quote')
if staticfiles_storage.exists(static_url.group('rest')):
return static_url.group(0)
else:
url = staticfiles_storage.url(prefix + static_url.group('rest')) url = staticfiles_storage.url(prefix + static_url.group('rest'))
return "".join([quote, url, quote]) return "".join([quote, url, quote])
...@@ -20,7 +23,7 @@ def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/'): ...@@ -20,7 +23,7 @@ def replace_urls(text, staticfiles_prefix=None, replace_prefix='/static/'):
return re.sub(r""" return re.sub(r"""
(?x) # flags=re.VERBOSE (?x) # flags=re.VERBOSE
(?P<quote>\\?['"]) # the opening quotes (?P<quote>\\?['"]) # the opening quotes
{prefix} # the prefix (?P<prefix>{prefix}) # the prefix
(?P<rest>.*?) # everything else in the url (?P<rest>.*?) # everything else in the url
(?P=quote) # the first matching closing quote (?P=quote) # the first matching closing quote
""".format(prefix=replace_prefix), replace_url, text) """.format(prefix=replace_prefix), replace_url, text)
...@@ -172,12 +172,8 @@ class XmlDescriptor(XModuleDescriptor): ...@@ -172,12 +172,8 @@ class XmlDescriptor(XModuleDescriptor):
log.debug('filepath=%s, resources_fs=%s' % (filepath, system.resources_fs)) log.debug('filepath=%s, resources_fs=%s' % (filepath, system.resources_fs))
try: try:
with system.resources_fs.open(filepath) as file: with system.resources_fs.open(filepath) as file:
try:
definition_xml = cls.file_to_xml(file) definition_xml = cls.file_to_xml(file)
except: except (ResourceNotFoundError, etree.XMLSyntaxError):
log.exception("Failed to parse xml in file %s" % filepath)
raise
except ResourceNotFoundError:
log.exception('Unable to load file contents at path %s' % filepath) log.exception('Unable to load file contents at path %s' % filepath)
return {'data': 'Error loading file contents at path %s' % filepath} return {'data': 'Error loading file contents at path %s' % filepath}
......
import json import json
import logging import logging
import settings
import uuid import uuid
from django.conf import settings from django.conf import settings
...@@ -13,8 +12,9 @@ import courseware.grades as grades ...@@ -13,8 +12,9 @@ import courseware.grades as grades
from certificates.models import GeneratedCertificate, certificate_state_for_student, revoke_certificate from certificates.models import GeneratedCertificate, certificate_state_for_student, revoke_certificate
from mitxmako.shortcuts import render_to_response, render_to_string from mitxmako.shortcuts import render_to_response, render_to_string
from student.models import UserProfile from student.models import UserProfile
from student.survey_questions import exit_survey_list_for_student #TODO: Finish migrating these changes from stable
from student.views import student_took_survey, record_exit_survey # 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") 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): ...@@ -186,7 +186,7 @@ if os.path.isdir(DATA_DIR):
# should no longer be added to STATICFILES # should no longer be added to STATICFILES
(course_dir, DATA_DIR / course_dir) (course_dir, DATA_DIR / course_dir)
for course_dir in os.listdir(DATA_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 # Locale/Internationalization
......
...@@ -89,57 +89,57 @@ nav.sequence-nav { ...@@ -89,57 +89,57 @@ nav.sequence-nav {
//video //video
&.seq_video_inactive { &.seq_video_inactive {
@extend .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; background-position: center;
} }
&.seq_video_visited { &.seq_video_visited {
@extend .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; background-position: center;
} }
&.seq_video_active { &.seq_video_active {
@extend .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; background-position: center;
} }
//other //other
&.seq_other_inactive { &.seq_other_inactive {
@extend .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; background-position: center;
} }
&.seq_other_visited { &.seq_other_visited {
@extend .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; background-position: center;
} }
&.seq_other_active { &.seq_other_active {
@extend .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; background-position: center;
} }
//vertical & problems //vertical & problems
&.seq_vertical_inactive, &.seq_problem_inactive { &.seq_vertical_inactive, &.seq_problem_inactive {
@extend .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; background-position: center;
} }
&.seq_vertical_visited, &.seq_problem_visited { &.seq_vertical_visited, &.seq_problem_visited {
@extend .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; background-position: center;
} }
&.seq_vertical_active, &.seq_problem_active { &.seq_vertical_active, &.seq_problem_active {
@extend .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; background-position: center;
} }
...@@ -229,7 +229,7 @@ nav.sequence-nav { ...@@ -229,7 +229,7 @@ nav.sequence-nav {
&.prev { &.prev {
a { a {
background-image: url('../../images/sequence-nav/previous-icon.png'); background-image: url('../images/sequence-nav/previous-icon.png');
&:hover { &:hover {
background-color: $cream; background-color: $cream;
...@@ -239,7 +239,7 @@ nav.sequence-nav { ...@@ -239,7 +239,7 @@ nav.sequence-nav {
&.next { &.next {
a { a {
background-image: url('../../images/sequence-nav/next-icon.png'); background-image: url('../images/sequence-nav/next-icon.png');
&:hover { &:hover {
background-color: $cream; background-color: $cream;
...@@ -310,7 +310,7 @@ section.course-content { ...@@ -310,7 +310,7 @@ section.course-content {
&.prev { &.prev {
a { 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%); border-right: 1px solid darken(#f6efd4, 20%);
&:hover { &:hover {
...@@ -321,7 +321,7 @@ section.course-content { ...@@ -321,7 +321,7 @@ section.course-content {
&.next { &.next {
a { a {
background-image: url('../../images/sequence-nav/next-icon.png'); background-image: url('../images/sequence-nav/next-icon.png');
&:hover { &:hover {
background-color: none; 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