merging inline html
This commit is contained in:
@@ -3,6 +3,7 @@ import django_comment_client.base.views
|
||||
|
||||
urlpatterns = patterns('django_comment_client.base.views',
|
||||
|
||||
url(r'upload$', 'upload', name='upload'),
|
||||
url(r'threads/(?P<thread_id>[\w\-]+)/update$', 'update_thread', name='update_thread'),
|
||||
url(r'threads/(?P<thread_id>[\w\-]+)/reply$', 'create_comment', name='create_comment'),
|
||||
url(r'threads/(?P<thread_id>[\w\-]+)/delete', 'delete_thread', name='delete_thread'),
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
import time
|
||||
import random
|
||||
import os
|
||||
import os.path
|
||||
import logging
|
||||
import urlparse
|
||||
|
||||
import comment_client
|
||||
|
||||
from django.core import exceptions
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.views.decorators.http import require_POST, require_GET
|
||||
from django.http import HttpResponse
|
||||
from django.utils import simplejson
|
||||
|
||||
import comment_client
|
||||
from django.views.decorators import csrf
|
||||
from django.core.files.storage import get_storage_class
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.conf import settings
|
||||
|
||||
class JsonResponse(HttpResponse):
|
||||
def __init__(self, data=None):
|
||||
@@ -183,3 +195,82 @@ def search(request, course_id):
|
||||
commentable_id = request.GET.get('commentable_id', None)
|
||||
response = comment_client.search(text, commentable_id)
|
||||
return JsonResponse(response)
|
||||
|
||||
@csrf.csrf_exempt
|
||||
@login_required
|
||||
@require_POST
|
||||
def upload(request, course_id):#ajax upload file to a question or answer
|
||||
"""view that handles file upload via Ajax
|
||||
"""
|
||||
|
||||
# check upload permission
|
||||
result = ''
|
||||
error = ''
|
||||
new_file_name = ''
|
||||
try:
|
||||
# TODO authorization
|
||||
#may raise exceptions.PermissionDenied
|
||||
#if request.user.is_anonymous():
|
||||
# msg = _('Sorry, anonymous users cannot upload files')
|
||||
# raise exceptions.PermissionDenied(msg)
|
||||
|
||||
#request.user.assert_can_upload_file()
|
||||
|
||||
# check file type
|
||||
f = request.FILES['file-upload']
|
||||
file_extension = os.path.splitext(f.name)[1].lower()
|
||||
if not file_extension in settings.DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES:
|
||||
file_types = "', '".join(settings.DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES)
|
||||
msg = _("allowed file types are '%(file_types)s'") % \
|
||||
{'file_types': file_types}
|
||||
raise exceptions.PermissionDenied(msg)
|
||||
|
||||
# generate new file name
|
||||
new_file_name = str(
|
||||
time.time()
|
||||
).replace(
|
||||
'.',
|
||||
str(random.randint(0,100000))
|
||||
) + file_extension
|
||||
|
||||
file_storage = get_storage_class()()
|
||||
# use default storage to store file
|
||||
file_storage.save(new_file_name, f)
|
||||
# check file size
|
||||
# byte
|
||||
size = file_storage.size(new_file_name)
|
||||
if size > settings.ASKBOT_MAX_UPLOAD_FILE_SIZE:
|
||||
file_storage.delete(new_file_name)
|
||||
msg = _("maximum upload file size is %(file_size)sK") % \
|
||||
{'file_size': settings.ASKBOT_MAX_UPLOAD_FILE_SIZE}
|
||||
raise exceptions.PermissionDenied(msg)
|
||||
|
||||
except exceptions.PermissionDenied, e:
|
||||
error = unicode(e)
|
||||
except Exception, e:
|
||||
logging.critical(unicode(e))
|
||||
error = _('Error uploading file. Please contact the site administrator. Thank you.')
|
||||
|
||||
if error == '':
|
||||
result = 'Good'
|
||||
file_url = file_storage.url(new_file_name)
|
||||
parsed_url = urlparse.urlparse(file_url)
|
||||
file_url = urlparse.urlunparse(
|
||||
urlparse.ParseResult(
|
||||
parsed_url.scheme,
|
||||
parsed_url.netloc,
|
||||
parsed_url.path,
|
||||
'', '', ''
|
||||
)
|
||||
)
|
||||
else:
|
||||
result = ''
|
||||
file_url = ''
|
||||
|
||||
return JsonResponse({
|
||||
'result': {
|
||||
'msg': result,
|
||||
'error': error,
|
||||
'file_url': file_url,
|
||||
}
|
||||
})
|
||||
|
||||
@@ -32,6 +32,7 @@ def render_discussion(request, course_id, threads, discussion_id=None, search_te
|
||||
'discussion_id': discussion_id,
|
||||
'search_bar': render_search_bar(request, course_id, discussion_id, text=search_text),
|
||||
'user_info': comment_client.get_user_info(request.user.id, raw=True),
|
||||
'tags': comment_client.get_threads_tags(raw=True),
|
||||
'course_id': course_id,
|
||||
}
|
||||
return render_to_string('discussion/inline.html', context)
|
||||
@@ -78,6 +79,7 @@ def render_single_thread(request, course_id, thread_id):
|
||||
context = {
|
||||
'thread': comment_client.get_thread(thread_id, recursive=True),
|
||||
'user_info': comment_client.get_user_info(request.user.id, raw=True),
|
||||
'tags': comment_client.get_threads_tags(raw=True),
|
||||
'course_id': course_id,
|
||||
}
|
||||
return render_to_string('discussion/single_thread.html', context)
|
||||
@@ -91,7 +93,6 @@ def single_thread(request, course_id, thread_id):
|
||||
'init': '',
|
||||
'content': render_single_thread(request, course_id, thread_id),
|
||||
'accordion': '',
|
||||
'user_info': comment_client.get_user_info(request.user.id, raw=True),
|
||||
'course': course,
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import djcelery
|
||||
from path import path
|
||||
|
||||
from .askbotsettings import * # this is where LIVESETTINGS_OPTIONS comes from
|
||||
from .discussionsettings import *
|
||||
|
||||
################################### FEATURES ###################################
|
||||
COURSEWARE_ENABLED = True
|
||||
|
||||
1
lms/envs/discussionsettings.py
Normal file
1
lms/envs/discussionsettings.py
Normal file
@@ -0,0 +1 @@
|
||||
DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')
|
||||
@@ -11,6 +11,9 @@ def delete_threads(commentable_id, *args, **kwargs):
|
||||
def get_threads(commentable_id, recursive=False, *args, **kwargs):
|
||||
return _perform_request('get', _url_for_threads(commentable_id), {'recursive': recursive}, *args, **kwargs)
|
||||
|
||||
def get_threads_tags(*args, **kwargs):
|
||||
return _perform_request('get', _url_for_threads_tags(), {}, *args, **kwargs)
|
||||
|
||||
def create_thread(commentable_id, attributes, *args, **kwargs):
|
||||
return _perform_request('post', _url_for_threads(commentable_id), attributes, *args, **kwargs)
|
||||
|
||||
@@ -126,3 +129,6 @@ def _url_for_user(user_id):
|
||||
|
||||
def _url_for_search():
|
||||
return "{prefix}/search".format(prefix=PREFIX)
|
||||
|
||||
def _url_for_threads_tags():
|
||||
return "{prefix}/threads/tags".format(prefix=PREFIX)
|
||||
|
||||
@@ -102,6 +102,7 @@ $ ->
|
||||
text
|
||||
|
||||
if Markdown?
|
||||
|
||||
Markdown.getMathCompatibleConverter = ->
|
||||
converter = Markdown.getSanitizingConverter()
|
||||
processor = new MathJaxProcessor()
|
||||
@@ -109,11 +110,13 @@ $ ->
|
||||
converter.hooks.chain "postConversion", processor.replaceMath
|
||||
converter
|
||||
|
||||
Markdown.makeWmdEditor = (elem, appended_id) ->
|
||||
Markdown.makeWmdEditor = (elem, appended_id, imageUploadUrl) ->
|
||||
$elem = $(elem)
|
||||
|
||||
if not $elem.length
|
||||
console.log "warning: elem for makeWmdEditor doesn't exist"
|
||||
return
|
||||
|
||||
if not $elem.find(".wmd-panel").length
|
||||
_append = appended_id || ""
|
||||
$wmdPanel = $("<div>").addClass("wmd-panel")
|
||||
@@ -121,8 +124,42 @@ $ ->
|
||||
.append($("<textarea>").addClass("wmd-input").attr("id", "wmd-input#{_append}"))
|
||||
.append($("<div>").attr("id", "wmd-preview#{_append}").addClass("wmd-panel wmd-preview"))
|
||||
$elem.append($wmdPanel)
|
||||
|
||||
converter = Markdown.getMathCompatibleConverter()
|
||||
editor = new Markdown.Editor(converter, appended_id)
|
||||
|
||||
ajaxFileUpload = (imageUploadUrl, input, startUploadHandler) ->
|
||||
$("#loading").ajaxStart(-> $(this).show()).ajaxComplete(-> $(this).hide())
|
||||
$("#upload").ajaxStart(-> $(this).hide()).ajaxComplete(-> $(this).show())
|
||||
$.ajaxFileUpload
|
||||
url: imageUploadUrl
|
||||
secureuri: false
|
||||
fileElementId: 'file-upload'
|
||||
dataType: 'json'
|
||||
success: (data, status) ->
|
||||
fileURL = data['result']['file_url']
|
||||
error = data['result']['error']
|
||||
if error != ''
|
||||
alert error
|
||||
if startUploadHandler
|
||||
$('#file-upload').unbind('change').change(startUploadHandler)
|
||||
console.log error
|
||||
else
|
||||
$(input).attr('value', fileURL)
|
||||
error: (data, status, e) ->
|
||||
alert(e)
|
||||
if startUploadHandler
|
||||
$('#file-upload').unbind('change').change(startUploadHandler)
|
||||
|
||||
imageUploadHandler = (elem, input) ->
|
||||
console.log "here"
|
||||
ajaxFileUpload(imageUploadUrl, input, imageUploadHandler)
|
||||
|
||||
editor = new Markdown.Editor(
|
||||
converter,
|
||||
appended_id, # idPostfix
|
||||
null, # help handler
|
||||
imageUploadHandler
|
||||
)
|
||||
delayRenderer = new MathJaxDelayRenderer()
|
||||
editor.hooks.chain "onPreviewPush", (text, previewSet) ->
|
||||
delayRenderer.render
|
||||
|
||||
@@ -43,6 +43,7 @@ Discussion =
|
||||
delete_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/delete"
|
||||
upvote_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/upvote"
|
||||
downvote_comment : "/courses/#{$$course_id}/discussion/comments/#{param}/downvote"
|
||||
upload : "/courses/#{$$course_id}/discussion/upload"
|
||||
search : "/courses/#{$$course_id}/discussion/forum/search"
|
||||
}[name]
|
||||
|
||||
@@ -89,7 +90,7 @@ Discussion =
|
||||
|
||||
newPostBody = $(discussion).find(".new-post-body")
|
||||
if newPostBody.length
|
||||
Markdown.makeWmdEditor newPostBody, "-new-post-body-#{$(discussion).attr('_id')}"
|
||||
Markdown.makeWmdEditor newPostBody, "-new-post-body-#{$(discussion).attr('_id')}", Discussion.urlFor('upload')
|
||||
|
||||
initializeWatchThreads = (index, thread) ->
|
||||
$thread = $(thread)
|
||||
@@ -175,7 +176,7 @@ Discussion =
|
||||
|
||||
$discussionContent.append(editView)
|
||||
|
||||
Markdown.makeWmdEditor $local(".comment-edit"), "-comment-edit-#{id}"
|
||||
Markdown.makeWmdEditor $local(".comment-edit"), "-comment-edit-#{id}", Discussion.urlFor('upload')
|
||||
cancelReply = generateDiscussionLink("discussion-cancel-reply", "Cancel", handleCancelReply)
|
||||
submitReply = generateDiscussionLink("discussion-submit-reply", "Submit", handleSubmitReply)
|
||||
$local(".discussion-link").hide()
|
||||
@@ -230,10 +231,17 @@ Discussion =
|
||||
$local(".discussion-vote-down").click ->
|
||||
handleVote(this, "down")
|
||||
|
||||
initializeContent: (content) ->
|
||||
$content = $(content)
|
||||
$local = generateLocal($content.children(".discussion-content"))
|
||||
raw_text = $local(".content-body").html()
|
||||
converter = Markdown.getMathCompatibleConverter()
|
||||
$local(".content-body").html(converter.makeHtml(raw_text))
|
||||
|
||||
bindDiscussionEvents: (discussion) ->
|
||||
$discussion = $(discussion)
|
||||
$discussionNonContent = $discussion.children(".discussion-non-content")
|
||||
$local = (selector) -> $discussionNonContent.find(selector)
|
||||
$local = generateLocal($discussionNonContent)#(selector) -> $discussionNonContent.find(selector)
|
||||
|
||||
id = $discussion.attr("_id")
|
||||
|
||||
@@ -266,7 +274,9 @@ Discussion =
|
||||
$local(".new-post-form").submit()
|
||||
|
||||
$discussion.find(".thread").each (index, thread) ->
|
||||
Discussion.initializeContent(thread)
|
||||
Discussion.bindContentEvents(thread)
|
||||
|
||||
$discussion.find(".comment").each (index, comment) ->
|
||||
Discussion.initializeContent(comment)
|
||||
Discussion.bindContentEvents(comment)
|
||||
|
||||
@@ -28,7 +28,28 @@
|
||||
|
||||
<%static:js group='courseware'/>
|
||||
|
||||
<%include file="mathjax_include.html" />
|
||||
<script type="text/x-mathjax-config">
|
||||
MathJax.Hub.Config({
|
||||
tex2jax: {
|
||||
inlineMath: [
|
||||
["$","$"],
|
||||
],
|
||||
displayMath: [
|
||||
["$$","$$"],
|
||||
]
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- This must appear after all mathjax-config blocks, so it is after the imports from the other templates.
|
||||
It can't be run through static.url because MathJax uses crazy url introspection to do lazy loading of
|
||||
MathJax extension libraries -->
|
||||
<script type="text/javascript" src="/static/js/vendor/mathjax-MathJax-c9db6ac/MathJax.js?config=TeX-MML-AM_HTMLorMML-full"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/split.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/jquery.ajaxfileupload.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/Markdown.Converter.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/Markdown.Sanitizer.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/Markdown.Editor.js')}"></script>
|
||||
|
||||
<!-- TODO: http://docs.jquery.com/Plugins/Validation -->
|
||||
<script type="text/javascript">
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
## It can't be run through static.url because MathJax uses crazy url introspection to do lazy loading of MathJax extension libraries
|
||||
<script type="text/javascript" src="/static/js/vendor/mathjax-MathJax-c9db6ac/MathJax.js?config=TeX-MML-AM_HTMLorMML-full"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/split.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/jquery.ajaxfileupload.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/Markdown.Converter.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/Markdown.Sanitizer.js')}"></script>
|
||||
<script type="text/javascript" src="${static.url('js/vendor/Markdown.Editor.js')}"></script>
|
||||
|
||||
@@ -7,11 +7,10 @@
|
||||
</div>
|
||||
${search_bar}
|
||||
<form class="new-post-form" _id="${discussion_id}">
|
||||
<input class="searchInput" type="text" autocomplete="off" placeholder="Comment Text"/>
|
||||
<div class="new-post-body">
|
||||
</div>
|
||||
<input type="text" class="new-post-title" placeholder="Title"/>
|
||||
<div class="new-post-body"></div>
|
||||
<input type="text" class="new-pot-tags" placeholder="tag1, tag2"/>
|
||||
<a class="discussion-new-post" href="javascript:void(0)">New Post</a>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
% for thread in threads:
|
||||
@@ -19,7 +18,13 @@
|
||||
% endfor
|
||||
</section>
|
||||
|
||||
<%!
|
||||
def escape_quotes(text):
|
||||
return text.replace('\"', '\\\"').replace("\'", "\\\'")
|
||||
%>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $$user_info = JSON.parse('${user_info}');
|
||||
var $$user_info = JSON.parse('${user_info | escape_quotes}');
|
||||
var $$course_id = "${course_id}";
|
||||
var $$tags = JSON.parse("${tags | escape_quotes}");
|
||||
</script>
|
||||
|
||||
@@ -5,7 +5,13 @@
|
||||
${renderer.render_thread(course_id, thread, edit_thread=True, show_comments=True)}
|
||||
</section>
|
||||
|
||||
<%!
|
||||
def escape_quotes(text):
|
||||
return text.replace('\"', '\\\"').replace("\'", "\\\'")
|
||||
%>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $$user_info = JSON.parse('${user_info}');
|
||||
var $$user_info = JSON.parse('${user_info | escape_quotes}');
|
||||
var $$course_id = "${course_id}";
|
||||
var $$tags = JSON.parse("${tags | escape_quotes}");
|
||||
</script>
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<div class="discussion-upper-wrapper clearfix">
|
||||
${render_vote(thread)}
|
||||
<div class="discussion-right-wrapper clearfix">
|
||||
<a class="thread-title" name="${thread['id']}" href="${url_for_thread}">${thread['title']}</a>
|
||||
<a class="thread-title" name="${thread['id']}" href="${url_for_thread}">${thread['title'] | h}</a>
|
||||
<div class="discussion-content-view">
|
||||
<div class="thread-body">${thread['body']}</div>
|
||||
<div class="content-body thread-body">${thread['body'] | h}</div>
|
||||
<div class="info">
|
||||
${render_info(thread)}
|
||||
% if edit_thread:
|
||||
@@ -45,7 +45,7 @@
|
||||
${render_vote(comment)}
|
||||
<div class="discussion-right-wrapper">
|
||||
<div class="discussion-content-view">
|
||||
<a class="comment-body" name="${comment['id']}">${comment['body']}</a>
|
||||
<a class="content-body comment-body" name="${comment['id']}">${comment['body'] | h}</a>
|
||||
<div class="info">
|
||||
${render_info(comment)}
|
||||
${render_reply()}
|
||||
|
||||
Reference in New Issue
Block a user