merging inline html

This commit is contained in:
Brittany Cheng
2012-07-28 18:18:47 -04:00
17 changed files with 432 additions and 3559 deletions

View File

@@ -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'),

View File

@@ -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,
}
})

View File

@@ -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,
}

View File

@@ -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

View File

@@ -0,0 +1 @@
DISCUSSION_ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff')

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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">

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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()}