def complete(request, submission_id): """ When a student has completed a quest, or is commenting on an already completed quest, this view is called - The submission is marked as completed (by the student) - If the quest is automatically approved, then the submission is also marked as approved, and available quests are recalculated directly/synchromously, so that their available quest list is up to date """ submission = get_object_or_404(QuestSubmission, pk=submission_id) origin_path = submission.get_absolute_url() # http://stackoverflow.com/questions/22470637/django-show-validationerror-in-template if request.method == "POST": # for some reason Summernote is submitting the form in the background when an image is added or # dropped into the widget We need to ignore that submission # https://github.com/summernote/django-summernote/issues/362 if 'complete' not in request.POST and 'comment' not in request.POST: raise Http404("unrecognized submit button") # form = CommentForm(request.POST or None, wysiwyg=True, label="") # form = SubmissionQuickReplyForm(request.POST) form = SubmissionForm(request.POST, request.FILES) if form.is_valid(): comment_text = form.cleaned_data.get('comment_text') if not comment_text: if submission.quest.verification_required and not request.FILES: messages.error( request, "Please read the Submission Instructions more carefully. " "You are expected to attach something or comment to complete this quest!" ) return redirect(origin_path) elif 'comment' in request.POST and not request.FILES: messages.error(request, "Please leave a comment.") return redirect(origin_path) else: comment_text = "(submitted without comment)" comment_new = Comment.objects.create_comment( user=request.user, path=origin_path, text=comment_text, target=submission, ) if request.FILES: for afile in request.FILES.getlist('attachments'): newdoc = Document(docfile=afile, comment=comment_new) newdoc.save() if 'complete' in request.POST: note_verb = "completed" msg_text = "Quest completed" affected_users = [] if submission.quest.verification_required: msg_text += ", awaiting approval." else: note_verb += " (auto-approved quest)" msg_text += " and automatically approved." msg_text += " Please give me a moment to calculate what new quests this should make available to you." msg_text += " Try refreshing your browser in a few moments. Thanks! <br>—{deck_ai}" msg_text = msg_text.format( deck_ai=SiteConfig.get().deck_ai) icon = "<i class='fa fa-shield fa-lg'></i>" # Notify teacher if they are specific to quest but are not the student's current teacher # current teacher doesn't need the notification because they'll see it in their approvals tabs already if submission.quest.specific_teacher_to_notify \ and submission.quest.specific_teacher_to_notify not in request.user.profile.current_teachers(): affected_users.append( submission.quest.specific_teacher_to_notify) # Send notification to current teachers when a comment is left on an auto-approved quest # since these quests don't appear in the approvals tab, teacher would never know about the comment. if form.cleaned_data.get( 'comment_text' ) and not submission.quest.verification_required: affected_users.extend( request.user.profile.current_teachers()) submission.mark_completed() if not submission.quest.verification_required: submission.mark_approved() # Immediate/synchronous recalculation of available quests: # NOW ASYNCH TO PREVENT HUGE DELAYS! update_quest_conditions_for_user.apply_async( args=[request.user.id]) elif 'comment' in request.POST: note_verb = "commented on" msg_text = "Quest commented on." icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-comment-o fa-stack-2x text-info'></i>" + \ "</span>" affected_users = [] if request.user.is_staff: affected_users = [ submission.user, ] else: # student comment # student's teachers affected_users.extend( request.user.profile.current_teachers( )) # User.objects.filter(is_staff=True) # add quest's teacher if necessary if submission.quest.specific_teacher_to_notify: affected_users.append( submission.quest.specific_teacher_to_notify) # remove doubles/flatten affected_users = set(affected_users) else: raise Http404("unrecognized submit button") notify.send( request.user, action=comment_new, target=submission, recipient=submission.user, affected_users=affected_users, verb=note_verb, icon=icon, ) messages.success(request, msg_text) return redirect("quests:quests") else: context = { "heading": submission.quest.name, "submission": submission, # "comments": comments, "submission_form": form, "anchor": "submission-form-" + str(submission.quest.id), # "reply_comment_form": reply_comment_form, } return render(request, 'quest_manager/submission.html', context) else: raise Http404
def approve(request, submission_id): submission = get_object_or_404(QuestSubmission, pk=submission_id) origin_path = submission.get_absolute_url() if request.method == "POST": # currently only the big form has files. Need a more robust way to determine... if request.FILES or request.POST.get("awards"): if request.user.is_staff: form = SubmissionFormStaff(request.POST, request.FILES) else: form = SubmissionForm(request.POST, request.FILES) else: form = SubmissionQuickReplyForm(request.POST) if form.is_valid(): # handle badge assertion comment_text_addition = "" badge = form.cleaned_data.get('award') if badge: badges = [badge] else: badges = form.cleaned_data.get('awards') if badges: for badge in badges: # badge = get_object_or_404(Badge, pk=badge_id) new_assertion = BadgeAssertion.objects.create_assertion( submission.user, badge, request.user) messages.success( request, ("Badge " + str(new_assertion) + " granted to " + str(new_assertion.user))) comment_text_addition += "<p></br><i class='fa fa-certificate text-warning'></i> The <b>" + \ badge.name + "</b> badge was granted for this quest " + \ "<i class='fa fa-certificate text-warning'></i></p>" # handle with quest comments blank_comment_text = "" if 'approve_button' in request.POST: note_verb = "approved" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-check fa-stack-2x text-success'></i>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "</span>" blank_comment_text = SiteConfig.get().blank_approval_text submission.mark_approved() elif 'comment_button' in request.POST: note_verb = "commented on" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-comment-o fa-stack-2x text-info'></i>" + \ "</span>" blank_comment_text = "(no comment added)" elif 'return_button' in request.POST: note_verb = "returned" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-ban fa-stack-2x text-danger'></i>" + \ "</span>" blank_comment_text = SiteConfig.get().blank_return_text submission.mark_returned() else: raise Http404("unrecognized submit button") comment_text_form = form.cleaned_data.get('comment_text') if not comment_text_form: comment_text = blank_comment_text else: comment_text = comment_text_form comment_new = Comment.objects.create_comment(user=request.user, path=origin_path, text=comment_text + comment_text_addition, target=submission) # handle files if request.FILES: for afile in request.FILES.getlist('attachments'): newdoc = Document(docfile=afile, comment=comment_new) newdoc.save() # don't say "with" in notification if no comment was entered if not comment_text_form: action = None else: action = comment_new affected_users = [ submission.user, ] # if the staff member approving/commenting/retruning the submission isn't # one of the student's teachers then notify the student's teachers too # If they have no teachers (e.g. this quest is available outside of a course # and the student is not in a course) then nothign will be appended anyway teachers_list = list(submission.user.profile.current_teachers()) if request.user not in teachers_list: affected_users.extend(teachers_list) notify.send( request.user, action=action, target=submission, recipient=submission.user, affected_users=affected_users, verb=note_verb, icon=icon, ) message_string = "<a href='" + origin_path + "'>Submission of " + \ submission.quest.name + "</a> " + note_verb + \ " for <a href='" + submission.user.profile.get_absolute_url() + "'>" + \ submission.user.username + "</a>" messages.success(request, message_string) return redirect("quests:approvals") else: # messages.error(request, "There was an error with your comment. Maybe you need to type something?") # return redirect(origin_path) # rendering here with the context allows validation errors to be displayed context = { "heading": submission.quest.name, "submission": submission, # "comments": comments, "submission_form": form, "anchor": "submission-form-" + str(submission.quest.id), # "reply_comment_form": reply_comment_form, } return render(request, 'quest_manager/submission.html', context) else: raise Http404
def complete(request, submission_id): submission = get_object_or_404(QuestSubmission, pk=submission_id) origin_path = submission.get_absolute_url() # http://stackoverflow.com/questions/22470637/django-show-validationerror-in-template if request.method == "POST": # form = CommentForm(request.POST or None, wysiwyg=True, label="") # form = SubmissionQuickReplyForm(request.POST) form = SubmissionForm(request.POST, request.FILES) if form.is_valid(): comment_text = form.cleaned_data.get('comment_text') if not comment_text: if submission.quest.verification_required and not request.FILES: messages.error( request, "Please read the Submission Instructions more carefully. " "You are expected to attach something or comment to complete this quest!" ) return redirect(origin_path) else: comment_text = "(submitted without comment)" comment_new = Comment.objects.create_comment( user=request.user, path=origin_path, text=comment_text, target=submission, ) if request.FILES: file_list = request.FILES.getlist('files') for afile in file_list: newdoc = Document(docfile=afile, comment=comment_new) newdoc.save() if 'complete' in request.POST: note_verb = "completed" if submission.quest.verification_required: note_verb += ", awaiting approval." else: note_verb += " and automatically approved." icon = "<i class='fa fa-shield fa-lg'></i>" # Notify teacher if they are specific to quest but are not the student's teacher if submission.quest.specific_teacher_to_notify \ and submission.quest.specific_teacher_to_notify not in request.user.profile.current_teachers(): affected_users = [ submission.quest.specific_teacher_to_notify, ] else: affected_users = None submission.mark_completed() ################### if not submission.quest.verification_required: submission.mark_approved() elif 'comment' in request.POST: note_verb = "commented on" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-comment-o fa-stack-2x text-info'></i>" + \ "</span>" affected_users = [] if request.user.is_staff: affected_users = [ submission.user, ] else: # student comment # student's teachers affected_users.extend( request.user.profile.current_teachers( )) # User.objects.filter(is_staff=True) # add quest's teacher if necessary if submission.quest.specific_teacher_to_notify: affected_users.append( submission.quest.specific_teacher_to_notify) # remove doubles/flatten affected_users = set(affected_users) else: raise Http404("unrecognized submit button") notify.send( request.user, action=comment_new, target=submission, recipient=submission.user, affected_users=affected_users, verb=note_verb, icon=icon, ) messages.success(request, ("Quest " + note_verb)) return redirect("quests:quests") else: context = { "heading": submission.quest.name, "submission": submission, # "comments": comments, "submission_form": form, "anchor": "submission-form-" + str(submission.quest.id), # "reply_comment_form": reply_comment_form, } return render(request, 'quest_manager/submission.html', context) else: raise Http404
def complete(request, submission_id): submission = get_object_or_404(QuestSubmission, pk=submission_id) origin_path = submission.get_absolute_url() # http://stackoverflow.com/questions/22470637/django-show-validationerror-in-template if request.method == "POST": # form = CommentForm(request.POST or None, wysiwyg=True, label="") # form = SubmissionQuickReplyForm(request.POST) form = SubmissionForm(request.POST, request.FILES) if form.is_valid(): comment_text = form.cleaned_data.get('comment_text') if not comment_text: if submission.quest.verification_required and not request.FILES: messages.error(request, "Please read the Submission Instructions more carefully. " "You are expected to attach something or comment to complete this quest!") return redirect(origin_path) else: comment_text = "(submitted without comment)" comment_new = Comment.objects.create_comment( user=request.user, path=origin_path, text=comment_text, target=submission, ) if request.FILES: file_list = request.FILES.getlist('files') for afile in file_list: newdoc = Document(docfile=afile, comment=comment_new) newdoc.save() if 'complete' in request.POST: note_verb = "completed" if submission.quest.verification_required: note_verb += ", awaiting approval." else: note_verb += " and automatically approved." icon = "<i class='fa fa-shield fa-lg'></i>" # Notify teacher if they are specific to quest but are not the student's teacher if submission.quest.specific_teacher_to_notify \ and submission.quest.specific_teacher_to_notify not in request.user.profile.current_teachers(): affected_users = [submission.quest.specific_teacher_to_notify, ] else: affected_users = None submission.mark_completed() ################### if not submission.quest.verification_required: submission.mark_approved() elif 'comment' in request.POST: note_verb = "commented on" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-comment-o fa-stack-2x text-info'></i>" + \ "</span>" affected_users = [] if request.user.is_staff: affected_users = [submission.user, ] else: # student comment # student's teachers affected_users.extend(request.user.profile.current_teachers()) # User.objects.filter(is_staff=True) # add quest's teacher if necessary if submission.quest.specific_teacher_to_notify: affected_users.append(submission.quest.specific_teacher_to_notify) # remove doubles/flatten affected_users = set(affected_users) else: raise Http404("unrecognized submit button") notify.send( request.user, action=comment_new, target=submission, recipient=submission.user, affected_users=affected_users, verb=note_verb, icon=icon, ) messages.success(request, ("Quest " + note_verb)) return redirect("quests:quests") else: context = { "heading": submission.quest.name, "submission": submission, # "comments": comments, "submission_form": form, "anchor": "submission-form-" + str(submission.quest.id), # "reply_comment_form": reply_comment_form, } return render(request, 'quest_manager/submission.html', context) else: raise Http404
def approve(request, submission_id): submission = get_object_or_404(QuestSubmission, pk=submission_id) origin_path = submission.get_absolute_url() if request.method == "POST": # currently only the big form has files. Need a more robust way to determine... if request.FILES: form = SubmissionForm(request.POST, request.FILES) else: form = SubmissionQuickReplyForm(request.POST) if form.is_valid(): # handle badge assertion comment_text_addition = "" badge = form.cleaned_data.get('award') if badge: # badge = get_object_or_404(Badge, pk=badge_id) new_assertion = BadgeAssertion.objects.create_assertion(submission.user, badge, request.user) messages.success(request, ("Badge " + str(new_assertion) + " granted to " + str(new_assertion.user))) comment_text_addition = "<p></br><i class='fa fa-certificate text-warning'></i> The <b>" + \ badge.name + "</b> badge was granted for this quest <i class='fa fa-certificate text-warning'></i></p>" # handle with quest comments blank_comment_text = "" if 'approve_button' in request.POST: note_verb = "approved" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-check fa-stack-2x text-success'></i>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "</span>" blank_comment_text = "(approved without comment)" submission.mark_approved() ############## elif 'comment_button' in request.POST: note_verb = "commented on" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-comment-o fa-stack-2x text-info'></i>" + \ "</span>" blank_comment_text = "(no comment added)" elif 'return_button' in request.POST: note_verb = "returned" icon = "<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-ban fa-stack-2x text-danger'></i>" + \ "</span>" blank_comment_text = "(returned without comment)" submission.mark_returned() ############## else: raise Http404("unrecognized submit button") comment_text_form = form.cleaned_data.get('comment_text') if not comment_text_form: comment_text = blank_comment_text else: comment_text = comment_text_form comment_new = Comment.objects.create_comment( user=request.user, path=origin_path, text=comment_text + comment_text_addition, target=submission ) # handle files if request.FILES: file_list = request.FILES.getlist('files') for afile in file_list: # print(afile) newdoc = Document(docfile=afile, comment=comment_new) newdoc.save() # don't say "with" in notification if no comment was entered if not comment_text_form: action = None else: action = comment_new affected_users = [submission.user, ] notify.send( request.user, action=action, target=submission, recipient=submission.user, affected_users=affected_users, verb=note_verb, icon=icon, ) message_string = "<a href='" + origin_path + "'>Submission of " + \ submission.quest.name + "</a> " + note_verb + \ " for <a href='" + submission.user.profile.get_absolute_url() + "'>" + submission.user.username + "</a>" messages.success(request, message_string) return redirect("quests:approvals") else: # messages.error(request, "There was an error with your comment. Maybe you need to type something?") # return redirect(origin_path) # rendering here with the context allows validation errors to be displayed context = { "heading": submission.quest.name, "submission": submission, # "comments": comments, "submission_form": form, "anchor": "submission-form-" + str(submission.quest.id), # "reply_comment_form": reply_comment_form, } return render(request, 'quest_manager/submission.html', context) else: raise Http404
def complete(request, submission_id): submission = get_object_or_404(QuestSubmission, pk=submission_id) origin_path = submission.get_absolute_url() if request.method == "POST": # form = CommentForm(request.POST or None, wysiwyg=True, label="") # form = SubmissionQuickReplyForm(request.POST) form = SubmissionForm(request.POST, request.FILES) if form.is_valid(): comment_text = form.cleaned_data.get('comment_text') if not comment_text: if submission.quest.verification_required: messages.error(request, "Please read the Submission Instructions more carefully. You are expected to submit something to complete this quest!") return redirect(origin_path) else: comment_text = "(submitted without comment)" comment_new = Comment.objects.create_comment( user = request.user, path = origin_path, text = comment_text, target = submission, ) if request.FILES: newdoc = Document( docfile = request.FILES['docfile'], comment = comment_new) newdoc.save() if 'complete' in request.POST: note_verb="completed" if submission.quest.verification_required: note_verb += ", awaiting approval." else: note_verb += " and automatically approved." icon="<i class='fa fa-shield fa-lg'></i>" affected_users = None submission.mark_completed() ################### if submission.quest.verification_required == False: submission.mark_approved() elif 'comment' in request.POST: note_verb="commented on" icon="<span class='fa-stack'>" + \ "<i class='fa fa-shield fa-stack-1x'></i>" + \ "<i class='fa fa-comment-o fa-stack-2x text-info'></i>" + \ "</span>" if request.user.is_staff: affected_users = [submission.user,] else: # student comment affected_users = User.objects.filter(is_staff=True) else: raise Http404("unrecognized submit button") notify.send( request.user, action=comment_new, target= submission, recipient=submission.user, affected_users=affected_users, verb=note_verb, icon=icon, ) messages.success(request, ("Quest " + note_verb)) return redirect("quests:quests") else: messages.error(request, "There was an error with your comment. Maybe your attachment was too big? 20MB max!") return redirect(origin_path) else: raise Http404