def cancel_reservation(request, course_slug, reservation_id): if request.method in ['POST', 'DELETE']: course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) reserv_remove = Reservation.objects.get(Q(id=reservation_id) & Q(user__id=request.user.id)) if reserv_remove is None: messages.error(request, _('You are not the owner of this reservation')) return HttpResponseRedirect(reverse('course_reservations', args=[course.slug])) cancel_limit = datetime.utcnow().replace(tzinfo=pytz.utc) cancel_limit += timedelta(0, reserv_remove.asset.cancelation_in_advance * 60) if reserv_remove.reservation_begins < cancel_limit: messages.error(request, _('Not enough time in advance to cancel this reservation.')) return HttpResponseRedirect(reverse('course_reservations', args=[course.slug])) reserv_remove.delete() return HttpResponseRedirect(reverse('course_reservations', args=[course.slug])) else: return HttpResponseNotAllowed(['POST', 'DELETE'])
def course_reviews(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) assignments = course_get_visible_peer_review_assignments(request.user, course) collection = get_db().get_collection('peer_review_submissions') submissions = collection.find({ 'author': request.user.id, 'course': course.id, }, {'kq': True, '_id': False}) submissions = [s['kq'] for s in submissions] user_submissions = [a.id for a in assignments if a.kq.id in submissions] return render_to_response('peerreview/reviews.html', { 'course': course, 'assignments': assignments, 'user_submissions': user_submissions, 'is_enrolled': is_enrolled, }, context_instance=RequestContext(request))
def course_review_upload(request, course_slug): if request.method == "POST": course = get_course_if_user_can_view_or_404(course_slug, request) file_to_upload = request.FILES.get('pr_file', None) submission_text = request.POST.get('pr-submission', '') kq = get_object_or_404(KnowledgeQuantum, id=request.POST.get('kq_id', 0)) unit = kq.unit if (file_to_upload.size / (1024 * 1024) >= settings.PEER_REVIEW_FILE_MAX_SIZE): messages.error(request, _('Your file is greater than the max allowed size (%d MB).') % settings.PEER_REVIEW_FILE_MAX_SIZE) return HttpResponseRedirect(reverse('course_classroom', args=[course_slug]) + "#unit%d/kq%d/p" % (unit.id, kq.id)) if (len(submission_text) >= settings.PEER_REVIEW_TEXT_MAX_SIZE): messages.error(request, _('Your text is greater than the max allowed size (%d characters).') % settings.PEER_REVIEW_TEXT_MAX_SIZE) return HttpResponseRedirect(reverse('course_classroom', args=[course_slug]) + "#unit%d/kq%d/p" % (unit.id, kq.id)) s3_upload(request.user.id, kq.id, file_to_upload.name, file_to_upload) file_url = s3_url(request.user.id, file_to_upload.name, kq.id) submission = { "author": request.user.id, "author_reviews": 0, "text": request.POST.get('pr-submission', ''), "file": file_url, "created": datetime.utcnow(), "reviews": 0, "course": course.id, "unit": unit.id, "kq": kq.id, } insert_p2p_if_does_not_exists_or_raise(submission) return HttpResponseRedirect(reverse('course_classroom', args=[course_slug]) + "#unit%d/kq%d/p" % (unit.id, kq.id))
def course_review_assign(request, course_slug, assignment_id): course = get_course_if_user_can_view_or_404(course_slug, request) assignment = get_object_or_404(PeerReviewAssignment, id=assignment_id) user_id = request.user.id is_enrolled = course.students.filter(id=user_id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) if assignment.kq.unit.course != course: messages.error(request, _('The selected peer review assignment is not part of this course.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) collection = get_db().get_collection('peer_review_submissions') submission = collection.find({ 'kq': assignment.kq.id, 'assigned_to': user_id }) if submission.count() > 0: messages.error(request, _('You already have a submission assigned.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) max_hours_assigned = timedelta(hours=getattr(settings, "PEER_REVIEW_ASSIGNATION_EXPIRE", 24)) assignation_expire = datetime.utcnow() - max_hours_assigned #Check number of course langs to assign a PeerReview is_user_lang_valid = False if course.languages.count() > 1: for lang in course.languages.all(): if request.user.get_profile().language == lang.abbr: is_user_lang_valid = True if is_user_lang_valid: submission = _get_peer_review_submission(user_id, assignment.kq.id, assignation_expire, request.user.get_profile().language) else: submission = _get_peer_review_submission(user_id, assignment.kq.id, assignation_expire) else: submission = _get_peer_review_submission(user_id, assignment.kq.id, assignation_expire) if submission.count() == 0: # Deactivate while it is finished #if course.languages.count() > 1 and is_user_lang_valid: # return HttpResponseRedirect(reverse('course_reviews_ignorelang', args=[course_slug, assignment.kq.id])) messages.error(request, _('There is no submission avaliable for you at this moment. Please, try again later.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) else: collection.update({ '_id': submission[0]['_id'] }, { '$set': { 'assigned_to': user_id, 'assigned_when': datetime.utcnow() } }) return HttpResponseRedirect(reverse('course_review_review', args=[course_slug, assignment_id]))
def course_extra_info(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() return render_to_response('courses/static_page.html', { 'course': course, 'is_enrolled': is_enrolled, # required due course nav templatetag 'is_teacher': is_teacher_test(request.user, course), 'static_page': course.static_page, }, context_instance=RequestContext(request))
def free_unenrollment(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) if request.method == 'POST': user = request.user course.students.through.objects.get(student=user, course=course).delete() success(request, _(u'You have successfully unenroll in the course %(course)s') % {'course': unicode(course)}) return HttpResponseRedirect(reverse('course_overview', args=(course.slug, )))
def course_classroom(request, course_slug): """ Main view of the course content (class). If the user is not enrolled we show him a message. If the course is not ready and the user is not admin we redirect the user to a denied access page. :permissions: login :context: course, is_enrolled, ask_admin, unit_list, is_teacher, peer_view .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready and not request.user.is_superuser: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) units = [] for u in get_units_available_for_user(course, request.user): unit = { 'id': u.id, 'title': u.title, 'unittype': u.unittype, 'badge_class': get_unit_badge_class(u), 'badge_tooltip': u.get_unit_type_name(), } units.append(unit) peer_review = { 'text_max_size': settings.PEER_REVIEW_TEXT_MAX_SIZE, 'file_max_size': settings.PEER_REVIEW_FILE_MAX_SIZE, } return render_to_response( 'courses/classroom.html', { 'course': course, 'unit_list': units, 'is_enrolled': is_enrolled, 'is_teacher': is_teacher_test(request.user, course), 'peer_review': peer_review }, context_instance=RequestContext(request))
def course_extra_info(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() return render_to_response( 'courses/static_page.html', { 'course': course, 'is_enrolled': is_enrolled, # required due course nav templatetag 'is_teacher': is_teacher_test(request.user, course), 'static_page': course.static_page, }, context_instance=RequestContext(request))
def course_reservations(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) active_reservations = [] for i in user_course_get_active_reservations(request.user, course): base = model_to_dict(i) base['concurrent'] = get_concurrent_reservations(i) base['asset'] = i.asset base['reserved_from'] = i.reserved_from active_reservations.append(base) past_reservations = [] for i in user_course_get_past_reservations(request.user, course): base = model_to_dict(i) base['concurrent'] = get_concurrent_reservations(i) base['asset'] = i.asset base['reserved_from'] = i.reserved_from past_reservations.append(base) pending_reservations = [] for i in user_course_get_pending_reservations(request.user, course): base = model_to_dict(i) base['concurrent'] = get_concurrent_reservations(i) base['asset'] = i.asset base['reserved_from'] = i.reserved_from pending_reservations.append(base) return render_to_response('assets/reservations.html', { 'course': course, 'is_enrolled': is_enrolled, 'active_reservations': active_reservations, 'past_reservations': past_reservations, 'pending_reservations': pending_reservations, }, context_instance=RequestContext(request))
def course_classroom(request, course_slug): """ Main view of the course content (class). If the user is not enrolled we show him a message. If the course is not ready and the user is not admin we redirect the user to a denied access page. :permissions: login :context: course, is_enrolled, ask_admin, unit_list, is_teacher, peer_view .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready and not request.user.is_superuser: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) units = [] for u in get_units_available_for_user(course, request.user): unit = { 'id': u.id, 'title': u.title, 'unittype': u.unittype, 'badge_class': get_unit_badge_class(u), 'badge_tooltip': u.get_unit_type_name(), } units.append(unit) peer_review = { 'text_max_size': settings.PEER_REVIEW_TEXT_MAX_SIZE, 'file_max_size': settings.PEER_REVIEW_FILE_MAX_SIZE, } return render_to_response('courses/classroom.html', { 'course': course, 'unit_list': units, 'is_enrolled': is_enrolled, 'is_teacher': is_teacher_test(request.user, course), 'peer_review': peer_review }, context_instance=RequestContext(request))
def course_reservations(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) is_ready, ask_admin, is_outdated = is_course_ready(course) if not is_ready: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) active_reservations = [] for i in user_course_get_active_reservations(request.user, course): base = model_to_dict(i) base['concurrent'] = get_concurrent_reservations(i) base['asset'] = i.asset base['reserved_from'] = i.reserved_from active_reservations.append(base) past_reservations = [] for i in user_course_get_past_reservations(request.user, course): base = model_to_dict(i) base['concurrent'] = get_concurrent_reservations(i) base['asset'] = i.asset base['reserved_from'] = i.reserved_from past_reservations.append(base) pending_reservations = [] for i in user_course_get_pending_reservations(request.user, course): base = model_to_dict(i) base['concurrent'] = get_concurrent_reservations(i) base['asset'] = i.asset base['reserved_from'] = i.reserved_from pending_reservations.append(base) return render_to_response('assets/reservations.html', { 'course': course, 'is_enrolled': is_enrolled, 'active_reservations': active_reservations, 'past_reservations': past_reservations, 'pending_reservations': pending_reservations, }, context_instance=RequestContext(request))
def reservation_create(request, course_slug, kq_id, asset_id): if request.method in ['POST', 'PUT']: course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) kq = get_object_or_404(KnowledgeQuantum, id=kq_id) asset = get_object_or_404(Asset, id=asset_id) try: availability = kq.asset_availability except AssetAvailability.DoesNotExist: messages.error(request, _('This nugget has no available asset')) return HttpResponseRedirect( reverse('course_reservations', args=[course_slug])) if not ('reservation_date' in request.POST and 'reservation_time' in request.POST): messages.error(request, _('No initial time specified')) return HttpResponseRedirect( reverse('course_reservations', args=[course_slug])) try: reservation_starts = datetime.strptime( request.POST['reservation_date'] + ' ' + request.POST['reservation_time'], '%Y-%m-%d %H:%M') except ValueError: messages.error(request, _('Incorrect booking time specified')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) did_book = book_asset( request.user, asset, availability, reservation_starts, reservation_starts + timedelta(0, asset.slot_duration * 60)) if did_book[0]: messages.success(request, did_book[1]) else: messages.error(request, did_book[1]) return HttpResponseRedirect( reverse('course_reservations', args=[course_slug])) else: return HttpResponseNotAllowed(['POST', 'PUT'])
def course_progress(request, course_slug): """ Main view for the user progress in the course. This will return the units for the user in the current course. :permissions: login :context: course, is_enrolled, ask_admin, course, unit_list, is_teacher .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) units = [] for u in get_units_available_for_user(course, request.user): unit = { 'id': u.id, 'title': u.title, 'unittype': u.unittype, 'badge_class': get_unit_badge_class(u), 'badge_tooltip': u.get_unit_type_name(), } units.append(unit) return render_to_response( 'courses/progress.html', { 'course': course, 'unit_list': units, 'is_enrolled': is_enrolled, # required due course nav templatetag 'is_teacher': is_teacher_test(request.user, course), }, context_instance=RequestContext(request))
def course_reviews(request, course_slug, kq_id=None, ignore_langs=False): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) is_ready, ask_admin, is_outdated = is_course_ready(course) is_teacher = is_teacher_test(request.user, course) if not is_ready and not is_teacher and not request.user.is_staff and not request.user.is_superuser: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) assignments = course_get_visible_peer_review_assignments(request.user, course) collection = get_db().get_collection('peer_review_submissions') submissions = collection.find({ 'author': request.user.id, 'course': course.id, }, {'kq': True, '_id': False}) submissions = [s['kq'] for s in submissions] user_submissions = [a.id for a in assignments if a.kq.id in submissions] tasks = get_tasks_available_for_user(course, request.user) group = get_group_by_user_and_course(request.user.id, course.id) return render_to_response('peerreview/reviews.html', { 'course': course, 'assignments': assignments, 'user_submissions': user_submissions, 'kq_id': kq_id, 'ignore_langs': ignore_langs, 'is_enrolled': is_enrolled, 'is_ready': is_ready, 'is_outdated': is_outdated, 'can_review': date.today() < course.end_date+timedelta(days=14), 'task_list': tasks[0], 'tasks_done': tasks[1], 'progress': get_course_progress_for_user(course, request.user), 'passed': has_user_passed_course(request.user, course), 'group': group, }, context_instance=RequestContext(request))
def clone_activity(request, course_slug): if request.method != 'POST': raise HttpResponseBadRequest user = request.user course = get_course_if_user_can_view_or_404(course_slug, request) course_student_relation = get_object_or_404(user.coursestudent_set, course=course) if not course_student_relation.can_clone_activity(): return HttpResponseBadRequest() course_student_relation.old_course_status = 'c' course_student_relation.save() clone_activity_user_course_task.apply_async(args=[user, course, get_language()], queue='courses') message = _(u'We are cloning the activity from %(course)s. You will receive an email soon') messages.success(request, message % {'course': unicode(course)}) return HttpResponseRedirect(course.get_absolute_url())
def announcement_detail(request, course_slug, announcement_id, announcement_slug): """ Show a detail view of an announcement. :context: course, announcement .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) announcement = get_object_or_404(Announcement, id=announcement_id) return render_to_response('courses/announcement.html', { 'course': course, 'announcement': announcement, 'template_base': 'courses/base_course.html' }, context_instance=RequestContext(request))
def course_review_upload(request, course_slug): if request.method == "POST": course = get_course_if_user_can_view_or_404(course_slug, request) file_to_upload = request.FILES.get('pr_file', None) submission_text = request.POST.get('pr-submission', '') kq = get_object_or_404(KnowledgeQuantum, id=request.POST.get('kq_id', 0)) unit = kq.unit if (file_to_upload.size / (1024 * 1024) >= settings.PEER_REVIEW_FILE_MAX_SIZE): messages.error( request, _('Your file is greater than the max allowed size (%d MB).') % settings.PEER_REVIEW_FILE_MAX_SIZE) return HttpResponseRedirect( reverse('course_classroom', args=[course_slug]) + "#unit%d/kq%d/p" % (unit.id, kq.id)) if (len(submission_text) >= settings.PEER_REVIEW_TEXT_MAX_SIZE): messages.error( request, _('Your text is greater than the max allowed size (%d characters).' ) % settings.PEER_REVIEW_TEXT_MAX_SIZE) return HttpResponseRedirect( reverse('course_classroom', args=[course_slug]) + "#unit%d/kq%d/p" % (unit.id, kq.id)) s3_upload(request.user.id, kq.id, file_to_upload.name, file_to_upload) file_url = s3_url(request.user.id, file_to_upload.name, kq.id) submission = { "author": request.user.id, "author_reviews": 0, "text": request.POST.get('pr-submission', ''), "file": file_url, "created": datetime.utcnow(), "reviews": 0, "course": course.id, "unit": unit.id, "kq": kq.id, } insert_p2p_if_does_not_exists_or_raise(submission) return HttpResponseRedirect( reverse('course_classroom', args=[course_slug]) + "#unit%d/kq%d/p" % (unit.id, kq.id))
def reservation_create(request, course_slug, kq_id, asset_id): if request.method in ['POST', 'PUT']: course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) kq = get_object_or_404(KnowledgeQuantum, id=kq_id) asset = get_object_or_404(Asset, id=asset_id) try: availability = kq.asset_availability except AssetAvailability.DoesNotExist: messages.error(request, _('This nugget has no available asset')) return HttpResponseRedirect(reverse('course_reservations', args=[course_slug])) if not ('reservation_date' in request.POST and 'reservation_time' in request.POST): messages.error(request, _('No initial time specified')) return HttpResponseRedirect(reverse('course_reservations', args=[course_slug])) try: reservation_starts = datetime.strptime(request.POST['reservation_date'] + ' ' + request.POST['reservation_time'], '%Y-%m-%d %H:%M') except ValueError: messages.error(request, _('Incorrect booking time specified')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) did_book = book_asset(request.user, asset, availability, reservation_starts, reservation_starts + timedelta(0, asset.slot_duration * 60)) if did_book[0]: messages.success(request, did_book[1]) else: messages.error(request, did_book[1]) return HttpResponseRedirect(reverse('course_reservations', args=[course_slug])) else: return HttpResponseNotAllowed(['POST', 'PUT'])
def clone_activity(request, course_slug): if request.method != 'POST': raise HttpResponseBadRequest user = request.user course = get_course_if_user_can_view_or_404(course_slug, request) course_student_relation = get_object_or_404(user.coursestudent_set, course=course) if not course_student_relation.can_clone_activity(): return HttpResponseBadRequest() course_student_relation.old_course_status = 'c' course_student_relation.save() clone_activity_user_course_task.apply_async( args=[user, course, get_language()], queue='courses') message = _( u'We are cloning the activity from %(course)s. You will receive an email soon' ) messages.success(request, message % {'course': unicode(course)}) return HttpResponseRedirect(course.get_absolute_url())
def course_progress(request, course_slug): """ Main view for the user progress in the course. This will return the units for the user in the current course. :permissions: login :context: course, is_enrolled, ask_admin, course, unit_list, is_teacher .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) units = [] for u in get_units_available_for_user(course, request.user): unit = { 'id': u.id, 'title': u.title, 'unittype': u.unittype, 'badge_class': get_unit_badge_class(u), 'badge_tooltip': u.get_unit_type_name(), } units.append(unit) return render_to_response('courses/progress.html', { 'course': course, 'unit_list': units, 'is_enrolled': is_enrolled, # required due course nav templatetag 'is_teacher': is_teacher_test(request.user, course), }, context_instance=RequestContext(request))
def free_enrollment(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) if request.method == 'POST': user = request.user old_course_status = 'f' if course.created_from: if course.created_from.students.filter(pk=user.pk): old_course_status = 'n' course.students.through.objects.create(student=user, course=course, old_course_status=old_course_status) if getattr(settings, 'FREE_ENROLLMENT_CONSISTENT', False): enroll_course_at_idp(request.user, course) success(request, _(u'Congratulations, you have successfully enroll in the course %(course)s') % {'course': unicode(course)}) return HttpResponseRedirect(reverse('course_overview', args=(course.slug, )))
def course_reviews(request, course_slug): course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) is_ready, ask_admin = is_course_ready(course) if not is_ready: return render_to_response('courses/no_content.html', { 'course': course, 'is_enrolled': is_enrolled, 'ask_admin': ask_admin, }, context_instance=RequestContext(request)) assignments = course_get_visible_peer_review_assignments( request.user, course) collection = get_db().get_collection('peer_review_submissions') submissions = collection.find( { 'author': request.user.id, 'course': course.id, }, { 'kq': True, '_id': False }) submissions = [s['kq'] for s in submissions] user_submissions = [a.id for a in assignments if a.kq.id in submissions] return render_to_response('peerreview/reviews.html', { 'course': course, 'assignments': assignments, 'user_submissions': user_submissions, 'is_enrolled': is_enrolled, }, context_instance=RequestContext(request))
def course_overview(request, course_slug): """ Show the course main page. This will show the main information about the course and the 'register to this course' button. .. note:: **use_old_calculus** is a compatibility method with old evaluation methods, which allowed the normal units to be evaluated. The new system does not evaluate normal units, only tasks and exams. :context: course, units, is_enrolled, is_teacher, request, course_teachers, announcements, use_old_calculus .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) if request.user.is_authenticated(): is_enrolled = course.students.filter(id=request.user.id).exists() is_teacher = is_teacher_test(request.user, course) else: is_enrolled = False is_teacher = False course_teachers = CourseTeacher.objects.filter(course=course) announcements = Announcement.objects.filter( course=course).order_by('datetime').reverse()[:5] units = get_units_available_for_user(course, request.user, True) return render_to_response( 'courses/overview.html', { 'course': course, 'units': units, 'is_enrolled': is_enrolled, 'is_teacher': is_teacher, 'request': request, 'course_teachers': course_teachers, 'announcements': announcements, 'use_old_calculus': settings.COURSES_USING_OLD_TRANSCRIPT, }, context_instance=RequestContext(request))
def cancel_reservation(request, course_slug, reservation_id): if request.method in ['POST', 'DELETE']: course = get_course_if_user_can_view_or_404(course_slug, request) is_enrolled = course.students.filter(id=request.user.id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) reserv_remove = Reservation.objects.get( Q(id=reservation_id) & Q(user__id=request.user.id)) if reserv_remove is None: messages.error(request, _('You are not the owner of this reservation')) return HttpResponseRedirect( reverse('course_reservations', args=[course.slug])) cancel_limit = datetime.utcnow().replace(tzinfo=pytz.utc) cancel_limit += timedelta( 0, reserv_remove.asset.cancelation_in_advance * 60) if reserv_remove.reservation_begins < cancel_limit: messages.error( request, _('Not enough time in advance to cancel this reservation.')) return HttpResponseRedirect( reverse('course_reservations', args=[course.slug])) reserv_remove.delete() return HttpResponseRedirect( reverse('course_reservations', args=[course.slug])) else: return HttpResponseNotAllowed(['POST', 'DELETE'])
def course_overview(request, course_slug): """ Show the course main page. This will show the main information about the course and the 'register to this course' button. .. note:: **use_old_calculus** is a compatibility method with old evaluation methods, which allowed the normal units to be evaluated. The new system does not evaluate normal units, only tasks and exams. :context: course, units, is_enrolled, is_teacher, request, course_teachers, announcements, use_old_calculus .. versionadded:: 0.1 """ course = get_course_if_user_can_view_or_404(course_slug, request) if request.user.is_authenticated(): is_enrolled = course.students.filter(id=request.user.id).exists() is_teacher = is_teacher_test(request.user, course) else: is_enrolled = False is_teacher = False course_teachers = CourseTeacher.objects.filter(course=course) announcements = Announcement.objects.filter(course=course).order_by('datetime').reverse()[:5] units = get_units_available_for_user(course, request.user, True) return render_to_response('courses/overview.html', { 'course': course, 'units': units, 'is_enrolled': is_enrolled, 'is_teacher': is_teacher, 'request': request, 'course_teachers': course_teachers, 'announcements': announcements, 'use_old_calculus': settings.COURSES_USING_OLD_TRANSCRIPT, }, context_instance=RequestContext(request))
def course_review_assign(request, course_slug, assignment_id): course = get_course_if_user_can_view_or_404(course_slug, request) assignment = get_object_or_404(PeerReviewAssignment, id=assignment_id) user_id = request.user.id is_enrolled = course.students.filter(id=user_id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) if assignment.kq.unit.course != course: messages.error(request, _('The selected peer review assignment is not part of this course.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) collection = get_db().get_collection('peer_review_submissions') submission = collection.find({ 'kq': assignment.kq.id, 'assigned_to': user_id }) if submission.count() > 0: messages.error(request, _('You already have a submission assigned.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) max_hours_assigned = timedelta(hours=getattr(settings, "PEER_REVIEW_ASSIGNATION_EXPIRE", 24)) assignation_expire = datetime.utcnow() - max_hours_assigned submission = collection.find({ 'kq': assignment.kq.id, '$or': [ { 'assigned_to': { '$exists': False }, }, { 'assigned_when': { '$lt': assignation_expire }, } ], 'author': { '$ne': user_id }, 'reviewers': { '$ne': user_id } }).sort([ ('reviews', pymongo.ASCENDING), ('author_reviews', pymongo.DESCENDING), ]).limit(1) if submission.count() == 0: messages.error(request, _('There is no submission avaliable for you at this moment. Please, try again later.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) else: collection.update({ '_id': submission[0]['_id'] }, { '$set': { 'assigned_to': user_id, 'assigned_when': datetime.utcnow() } }) return HttpResponseRedirect(reverse('course_review_review', args=[course_slug, assignment_id]))
def course_review_review(request, course_slug, assignment_id): course = get_course_if_user_can_view_or_404(course_slug, request) assignment = get_object_or_404(PeerReviewAssignment, id=assignment_id) user_id = request.user.id is_enrolled = course.students.filter(id=user_id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) if assignment.kq.unit.course != course: messages.error( request, _('The selected peer review assignment is not part of this course.' )) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) collection = get_db().get_collection('peer_review_submissions') submission = collection.find({ 'kq': assignment.kq.id, 'assigned_to': user_id }) if submission.count() == 0: messages.error(request, _('You don\'t have this submission assigned.')) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) submission_obj = submission[0] submitter = User.objects.get(id=int(submission_obj['author'])) criteria_initial = [{ 'evaluation_criterion_id': criterion.id } for criterion in assignment.criteria.all()] EvalutionCriteriaResponseFormSet = formset_factory( EvalutionCriteriaResponseForm, extra=0, max_num=len(criteria_initial)) if request.method == "POST": submission_form = ReviewSubmissionForm(request.POST) criteria_formset = EvalutionCriteriaResponseFormSet( request.POST, initial=criteria_initial) if criteria_formset.is_valid() and submission_form.is_valid(): criteria_values = [ (int(form.cleaned_data['evaluation_criterion_id']), int(form.cleaned_data['value'])) for form in criteria_formset ] try: review = save_review(assignment.kq, request.user, submitter, criteria_values, submission_form.cleaned_data['comments']) reviews = get_db().get_collection('peer_review_reviews') reviewed_count = reviews.find({ 'reviewer': user_id, 'kq': assignment.kq.id }).count() on_peerreviewreview_created_task.apply_async( args=[review, reviewed_count], queue='stats', ) current_site_name = get_current_site(request).name send_mail_to_submission_owner(current_site_name, assignment, review, submitter) except IntegrityError: messages.error( request, _('Your can\'t submit two times the same review.')) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) pending = assignment.minimum_reviewers - reviewed_count if pending > 0: messages.success( request, _('Your review has been submitted. You have to review at least %d exercises more.' ) % pending) else: messages.success(request, _('Your review has been submitted.')) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) else: submission_form = ReviewSubmissionForm() criteria_formset = EvalutionCriteriaResponseFormSet( initial=criteria_initial) max_hours_assigned = timedelta( hours=getattr(settings, "PEER_REVIEW_ASSIGNATION_EXPIRE", 24)) assigned_when = submission[0]["assigned_when"] assignation_expire = assigned_when + max_hours_assigned now = datetime.now(assigned_when.tzinfo) is_assignation_expired = now > assignation_expire return render_to_response('peerreview/review_review.html', { 'submission': submission[0], 'is_assignation_expired': is_assignation_expired, 'assignation_expire': assignation_expire, 'submission_form': submission_form, 'criteria_formset': criteria_formset, 'course': course, 'assignment': assignment, 'is_enrolled': is_enrolled, }, context_instance=RequestContext(request))
def course_review_review(request, course_slug, assignment_id): course = get_course_if_user_can_view_or_404(course_slug, request) assignment = get_object_or_404(PeerReviewAssignment, id=assignment_id) user_id = request.user.id is_enrolled = course.students.filter(id=user_id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect(reverse('course_overview', args=[course_slug])) if assignment.kq.unit.course != course: messages.error(request, _('The selected peer review assignment is not part of this course.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) collection = get_db().get_collection('peer_review_submissions') submission = collection.find({ 'kq': assignment.kq.id, 'assigned_to': user_id }) if submission.count() == 0: messages.error(request, _('You don\'t have this submission assigned.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) submission_obj = submission[0] submitter = User.objects.get(id=int(submission_obj['author'])) criteria_initial = [{'evaluation_criterion_id': criterion.id} for criterion in assignment.criteria.all()] EvalutionCriteriaResponseFormSet = formset_factory(EvalutionCriteriaResponseForm, extra=0, max_num=len(criteria_initial)) if request.method == "POST": submission_form = ReviewSubmissionForm(request.POST) criteria_formset = EvalutionCriteriaResponseFormSet(request.POST, initial=criteria_initial) if criteria_formset.is_valid() and submission_form.is_valid(): criteria_values = [(int(form.cleaned_data['evaluation_criterion_id']), int(form.cleaned_data['value'])) for form in criteria_formset] try: review = save_review(assignment.kq, request.user, submitter, criteria_values, submission_form.cleaned_data['comments']) reviews = get_db().get_collection('peer_review_reviews') reviewed_count = reviews.find({ 'reviewer': user_id, 'kq': assignment.kq.id }).count() review_scores = [int(form.cleaned_data['value']) for form in criteria_formset] if len(review_scores) > 0: score = float(sum(review_scores) / len(review_scores)) * 2 / 10 else: score = 1 extra = { 'geolocation': { 'lat': float(request.POST.get("context_geo_lat", "0.0")), 'lon': float(request.POST.get("context_geo_lon", "0.0")), }, 'url': request.build_absolute_uri(), 'result': { 'score': score, 'comment': submission_form.cleaned_data['comments'] } } on_peerreviewreview_created_task.apply_async( args=[review, reviewed_count, extra], queue='stats', ) current_site_name = get_current_site(request).name send_mail_to_submission_owner(current_site_name, assignment, review, submitter) except IntegrityError: messages.error(request, _('Your can\'t submit two times the same review.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) pending = assignment.minimum_reviewers - reviewed_count if pending > 0: messages.success(request, _('Your review has been submitted. You have to review at least %d exercises more.') % pending) else: messages.success(request, _('Your review has been submitted.')) return HttpResponseRedirect(reverse('course_reviews', args=[course_slug])) else: submission_form = ReviewSubmissionForm() criteria_formset = EvalutionCriteriaResponseFormSet(initial=criteria_initial) max_hours_assigned = timedelta(hours=getattr(settings, "PEER_REVIEW_ASSIGNATION_EXPIRE", 24)) assigned_when = submission[0]["assigned_when"] assignation_expire = assigned_when + max_hours_assigned now = datetime.now(assigned_when.tzinfo) is_assignation_expired = now > assignation_expire return render_to_response('peerreview/review_review.html', { 'submission': submission[0], 'is_assignation_expired': is_assignation_expired, 'assignation_expire': assignation_expire, 'submission_form': submission_form, 'criteria_formset': criteria_formset, 'course': course, 'assignment': assignment, 'is_enrolled': is_enrolled, }, context_instance=RequestContext(request))
def course_review_assign(request, course_slug, assignment_id): course = get_course_if_user_can_view_or_404(course_slug, request) assignment = get_object_or_404(PeerReviewAssignment, id=assignment_id) user_id = request.user.id is_enrolled = course.students.filter(id=user_id).exists() if not is_enrolled: messages.error(request, _('You are not enrolled in this course')) return HttpResponseRedirect( reverse('course_overview', args=[course_slug])) if assignment.kq.unit.course != course: messages.error( request, _('The selected peer review assignment is not part of this course.' )) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) collection = get_db().get_collection('peer_review_submissions') submission = collection.find({ 'kq': assignment.kq.id, 'assigned_to': user_id }) if submission.count() > 0: messages.error(request, _('You already have a submission assigned.')) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) max_hours_assigned = timedelta( hours=getattr(settings, "PEER_REVIEW_ASSIGNATION_EXPIRE", 24)) assignation_expire = datetime.utcnow() - max_hours_assigned submission = collection.find({ 'kq': assignment.kq.id, '$or': [{ 'assigned_to': { '$exists': False }, }, { 'assigned_when': { '$lt': assignation_expire }, }], 'author': { '$ne': user_id }, 'reviewers': { '$ne': user_id } }).sort([ ('reviews', pymongo.ASCENDING), ('author_reviews', pymongo.DESCENDING), ]).limit(1) if submission.count() == 0: messages.error( request, _('There is no submission avaliable for you at this moment. Please, try again later.' )) return HttpResponseRedirect( reverse('course_reviews', args=[course_slug])) else: collection.update({'_id': submission[0]['_id']}, { '$set': { 'assigned_to': user_id, 'assigned_when': datetime.utcnow() } }) return HttpResponseRedirect( reverse('course_review_review', args=[course_slug, assignment_id]))