def course_review(request, semester_id, course_id, offset=None): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) # check course state if not course.can_staff_review(): messages.warning(request, _("Reviewing not possible in current state.")) return redirect('evap.staff.views.semester_view', semester_id) reviewFS = modelformset_factory(TextAnswer, form=ReviewTextAnswerForm, can_order=False, can_delete=False, extra=0) # compute base queryset base_queryset = course.textanswer_set.filter(checked=False).values_list('id', flat=True).order_by('id') # figure out offset if offset is None: # get offset for current course key_name = "course_%d_offset" % course.id offset = cache.get(key_name) or 0 # store offset for next page view cache.set(key_name, (offset + TextAnswer.elements_per_page) % base_queryset.count()) else: offset = int(offset) # compute form queryset length = min(TextAnswer.elements_per_page, len(base_queryset)) form_queryset = course.textanswer_set.filter(pk__in=[base_queryset[(offset + i) % len(base_queryset)] for i in range(0, length)]) # create formset from sliced queryset formset = reviewFS(request.POST or None, queryset=form_queryset) if formset.is_valid(): count = 0 for form in formset: form.instance.save() if form.instance.checked: count = count + 1 if course.state == "evaluated" and course.is_fully_checked(): messages.success(request, _("Successfully reviewed {count} course answers for {course}. {course} is now fully reviewed.").format(count=count, course=course.name)) course.review_finished() course.save() return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) else: messages.success(request, _("Successfully reviewed {count} course answers for {course}.").format(count=count, course=course.name)) operation = request.POST.get('operation') if operation == 'save_and_next' and not course.is_fully_checked(): return custom_redirect('evap.staff.views.course_review', semester_id, course_id, tab=get_tab(request)) else: return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) else: template_data = dict(semester=semester, course=course, formset=formset, offset=offset, TextAnswer=TextAnswer) return render(request, "staff_course_review.html", template_data)
def course_unpublish(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) # check course state if not course.state == "published": messages.warning(request, _("The course '%s' cannot be unpublished, because it is not published.") % course.name) return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) if request.method == 'POST': course.revoke() course.save() return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) else: return render(request, "staff_course_unpublish.html", dict(semester=semester, course=course))
def helper_course_edit(request, semester, course): InlineContributionFormset = inlineformset_factory(Course, Contribution, formset=ContributionFormSet, form=ContributionForm, extra=1) form = CourseForm(request.POST or None, instance=course) formset = InlineContributionFormset(request.POST or None, instance=course, form_kwargs={'course': course}) editable = course.can_staff_edit operation = request.POST.get('operation') if form.is_valid() and formset.is_valid(): if operation not in ('save', 'approve'): raise SuspiciousOperation("Invalid POST operation") if not course.can_staff_edit or course.is_archived: raise SuspiciousOperation("Modifying this course is not allowed.") if course.state in ['evaluated', 'reviewed'] and course.is_in_evaluation_period(): course.reopen_evaluation() form.save(user=request.user) formset.save() if operation == 'approve': # approve course course.staff_approve() course.save() messages.success(request, _("Successfully updated and approved course.")) else: messages.success(request, _("Successfully updated course.")) return custom_redirect('staff:semester_view', semester.id) else: sort_formset(request, formset) template_data = dict(semester=semester, form=form, formset=formset, staff=True, state=course.state, editable=editable) return render(request, "staff_course_form.html", template_data)
def course_email(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) form = CourseEmailForm(request.POST or None, instance=course, export='export' in request.POST) if form.is_valid(): if form.export: email_addresses = '; '.join(form.email_addresses()) messages.info(request, _('Recipients: ') + '\n' + email_addresses) return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form)) form.send() missing_email_addresses = form.missing_email_addresses() if missing_email_addresses == 0: messages.success( request, _("Successfully sent emails for '%s'.") % course.name) else: messages.warning( request, _("Successfully sent some emails for '{course}', but {count} could not be reached as they do not have an email address." ).format(course=course.name, count=missing_email_addresses)) return custom_redirect('staff:semester_view', semester_id) else: return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form))
def faq_index(request): sections = FaqSection.objects.all() sectionFS = modelformset_factory(FaqSection, form=FaqSectionForm, can_delete=True, extra=1) formset = sectionFS(request.POST or None, queryset=sections) if formset.is_valid(): formset.save() messages.success(request, _("Successfully updated the FAQ sections.")) return custom_redirect('staff:faq_index') else: return render(request, "staff_faq_index.html", dict(formset=formset, sections=sections))
def degree_index(request): degrees = Degree.objects.all() degreeFS = modelformset_factory(Degree, form=DegreeForm, can_delete=True, extra=1) formset = degreeFS(request.POST or None, queryset=degrees) if formset.is_valid(): formset.save() messages.success(request, _("Successfully updated the degrees.")) return custom_redirect('staff:degree_index') else: return render(request, "staff_degree_index.html", dict(formset=formset, degrees=degrees))
def course_type_index(request): course_types = CourseType.objects.all() course_type_FS = modelformset_factory(CourseType, form=CourseTypeForm, can_delete=True, extra=1) formset = course_type_FS(request.POST or None, queryset=course_types) if formset.is_valid(): formset.save() messages.success(request, _("Successfully updated the course types.")) return custom_redirect('staff:course_type_index') else: return render(request, "staff_course_type_index.html", dict(formset=formset))
def course_email(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) form = CourseEmailForm(request.POST or None, instance=course) if form.is_valid(): form.send() if form.all_recepients_reachable(): messages.success(request, _("Successfully sent emails for '%s'.") % course.name) else: messages.warning(request, _("Successfully sent some emails for '{course}', but {count} could not be reached as they do not have an email address.").format(course=course.name, count=form.missing_email_addresses())) return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) else: return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form))
def course_delete(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) # check course state if not course.can_staff_delete(): messages.warning(request, _("The course '%s' cannot be deleted, because it is still in use.") % course.name) return redirect('evap.staff.views.semester_view', semester_id) if request.method == 'POST': course.delete() messages.success(request, _("Successfully deleted course.")) return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) else: return render(request, "staff_course_delete.html", dict(semester=semester, course=course))
def course_email(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id, semester=semester) form = CourseEmailForm(request.POST or None, instance=course, export='export' in request.POST) if form.is_valid(): if form.export: email_addresses = '; '.join(form.email_addresses()) messages.info(request, _('Recipients: ') + '\n' + email_addresses) return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form)) form.send() messages.success(request, _("Successfully sent emails for '%s'.") % course.name) return custom_redirect('staff:semester_view', semester_id) else: return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form))
def faq_section(request, section_id): section = get_object_or_404(FaqSection, id=section_id) questions = FaqQuestion.objects.filter(section=section) InlineQuestionFormset = inlineformset_factory(FaqSection, FaqQuestion, form=FaqQuestionForm, can_delete=True, extra=1, exclude=('section',)) formset = InlineQuestionFormset(request.POST or None, queryset=questions, instance=section) if formset.is_valid(): formset.save() messages.success(request, _("Successfully updated the FAQ questions.")) return custom_redirect('staff:faq_index') else: template_data = dict(formset=formset, section=section, questions=questions) return render(request, "staff_faq_section.html", template_data)
def course_delete(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) raise_permission_denied_if_archived(course) # check course state if not course.can_staff_delete: messages.warning(request, _("The course '%s' cannot be deleted, because it is still in use.") % course.name) return redirect("staff:semester_view", semester_id) if request.method == "POST": course.delete() messages.success(request, _("Successfully deleted course.")) return custom_redirect("staff:semester_view", semester_id) else: return render(request, "staff_course_delete.html", dict(semester=semester, course=course))
def degree_index(request): degrees = Degree.objects.all() degreeFS = modelformset_factory(Degree, form=DegreeForm, can_delete=True, extra=0) formset = degreeFS(request.POST or None, queryset=degrees) if formset.is_valid(): formset.save() messages.success(request, _("Successfully updated the degrees.")) return custom_redirect('staff:degree_index') else: return render(request, "staff_degree_index.html", dict(formset=formset, degrees=degrees))
def helper_course_edit(request, semester, course): InlineContributionFormset = inlineformset_factory( Course, Contribution, formset=ContributionFormSet, form=ContributionForm, extra=1) form = CourseForm(request.POST or None, instance=course) formset = InlineContributionFormset(request.POST or None, instance=course, form_kwargs={'course': course}) operation = request.POST.get('operation') if form.is_valid() and formset.is_valid(): if operation not in ('save', 'approve'): raise SuspiciousOperation("Invalid POST operation") if course.state in ['evaluated', 'reviewed' ] and course.is_in_evaluation_period: course.reopen_evaluation() form.save(user=request.user) formset.save() if operation == 'approve': # approve course course.staff_approve() course.save() messages.success(request, _("Successfully updated and approved course.")) else: messages.success(request, _("Successfully updated course.")) return custom_redirect('staff:semester_view', semester.id) else: sort_formset(request, formset) template_data = dict(semester=semester, course=course, form=form, formset=formset, staff=True) return render(request, "staff_course_form.html", template_data)
def course_delete(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) raise_permission_denied_if_archived(course) # check course state if not course.can_staff_delete: messages.warning( request, _("The course '%s' cannot be deleted, because it is still in use.") % course.name) return redirect('staff:semester_view', semester_id) if request.method == 'POST': course.delete() messages.success(request, _("Successfully deleted course.")) return custom_redirect('staff:semester_view', semester_id) else: return render(request, "staff_course_delete.html", dict(semester=semester, course=course))
def course_email(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) form = CourseEmailForm(request.POST or None, instance=course, export='export' in request.POST) if form.is_valid(): if form.export: email_addresses = '; '.join(form.email_addresses()) messages.info(request, _('Recipients: ') + '\n' + email_addresses) return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form)) form.send() missing_email_addresses = form.missing_email_addresses() if missing_email_addresses == 0: messages.success(request, _("Successfully sent emails for '%s'.") % course.name) else: messages.warning(request, _("Successfully sent some emails for '{course}', but {count} could not be reached as they do not have an email address.").format(course=course.name, count=missing_email_addresses)) return custom_redirect('staff:semester_view', semester_id) else: return render(request, "staff_course_email.html", dict(semester=semester, course=course, form=form))
def helper_course_edit(request, semester, course): InlineContributionFormset = inlineformset_factory( Course, Contribution, formset=ContributionFormSet, form=ContributionForm, extra=1, exclude=("course",) ) form = CourseForm(request.POST or None, instance=course) formset = InlineContributionFormset( request.POST or None, instance=course, queryset=course.contributions.exclude(contributor=None) ) if form.is_valid() and formset.is_valid(): if course.state in ["evaluated", "reviewed"] and course.is_in_evaluation_period: course.reopen_evaluation() form.save(user=request.user) formset.save() messages.success(request, _("Successfully updated course.")) return custom_redirect("staff:semester_view", semester.id) else: sort_formset(request, formset) template_data = dict(semester=semester, course=course, form=form, formset=formset, staff=True) return render(request, "staff_course_form.html", template_data)
def course_edit(request, semester_id, course_id): semester = get_object_or_404(Semester, id=semester_id) course = get_object_or_404(Course, id=course_id) ContributionFormset = inlineformset_factory(Course, Contribution, formset=ContributionFormSet, form=ContributionForm, extra=1, exclude=('course',)) # check course state if not course.can_staff_edit(): messages.warning(request, _("Editing not possible in current state.")) return redirect('evap.staff.views.semester_view', semester_id) form = CourseForm(request.POST or None, instance=course) formset = ContributionFormset(request.POST or None, instance=course, queryset=course.contributions.exclude(contributor=None)) if form.is_valid() and formset.is_valid(): form.save(user=request.user) formset.save() messages.success(request, _("Successfully updated course.")) return custom_redirect('evap.staff.views.semester_view', semester_id, tab=get_tab(request)) else: template_data = dict(semester=semester, course=course, form=form, formset=formset, staff=True) return render(request, "staff_course_form.html", template_data)
def faq_section(request, section_id): section = get_object_or_404(FaqSection, id=section_id) questions = FaqQuestion.objects.filter(section=section) InlineQuestionFormset = inlineformset_factory(FaqSection, FaqQuestion, form=FaqQuestionForm, can_delete=True, extra=1, exclude=('section', )) formset = InlineQuestionFormset(request.POST or None, queryset=questions, instance=section) if formset.is_valid(): formset.save() messages.success(request, _("Successfully updated the FAQ questions.")) return custom_redirect('staff:faq_index') else: template_data = dict(formset=formset, section=section, questions=questions) return render(request, "staff_faq_section.html", template_data)
def semester_course_operation(request, semester_id): semester = get_object_or_404(Semester, id=semester_id) raise_permission_denied_if_archived(semester) operation = request.GET.get('operation') if operation not in ['revertToNew', 'prepare', 'reenableEditorReview', 'approve', 'startEvaluation', 'publish', 'unpublish']: messages.error(request, _("Unsupported operation: ") + str(operation)) return custom_redirect('staff:semester_view', semester_id) if request.method == 'POST': course_ids = request.POST.getlist('course_ids') courses = Course.objects.filter(id__in=course_ids) send_email = request.POST.get('send_email') == 'on' if operation == 'revertToNew': helper_semester_course_operation_revert(request, courses) elif operation == 'prepare' or operation == 'reenableEditorReview': helper_semester_course_operation_prepare(request, courses, send_email) elif operation == 'approve': helper_semester_course_operation_approve(request, courses) elif operation == 'startEvaluation': helper_semester_course_operation_start(request, courses, send_email) elif operation == 'publish': helper_semester_course_operation_publish(request, courses, send_email) elif operation == 'unpublish': helper_semester_course_operation_unpublish(request, courses) return custom_redirect('staff:semester_view', semester_id) course_ids = request.GET.getlist('course') courses = Course.objects.filter(id__in=course_ids) if courses: current_state_name = STATES_ORDERED[courses[0].state] if operation == 'revertToNew': new_state_name = STATES_ORDERED['new'] elif operation == 'prepare' or operation == 'reenableEditorReview': new_state_name = STATES_ORDERED['prepared'] elif operation == 'approve': new_state_name = STATES_ORDERED['approved'] # remove courses without enough questionnaires courses_with_enough_questionnaires = [course for course in courses if course.has_enough_questionnaires()] difference = len(courses) - len(courses_with_enough_questionnaires) if difference: courses = courses_with_enough_questionnaires messages.warning(request, ungettext("%(courses)d course can not be approved, because it has not enough questionnaires assigned. It was removed from the selection.", "%(courses)d courses can not be approved, because they have not enough questionnaires assigned. They were removed from the selection.", difference) % {'courses': difference}) elif operation == 'startEvaluation': new_state_name = STATES_ORDERED['inEvaluation'] # remove courses with vote_end_date in the past courses_end_in_future = [course for course in courses if course.vote_end_date >= datetime.date.today()] difference = len(courses) - len(courses_end_in_future) if difference: courses = courses_end_in_future messages.warning(request, ungettext("%(courses)d course can not be approved, because it's evaluation end date lies in the past. It was removed from the selection.", "%(courses)d courses can not be approved, because their evaluation end dates lie in the past. They were removed from the selection.", difference) % {'courses': difference}) elif operation == 'publish': new_state_name = STATES_ORDERED['published'] elif operation == 'unpublish': new_state_name = STATES_ORDERED['reviewed'] if not courses: messages.warning(request, _("Please select at least one course.")) return custom_redirect('staff:semester_view', semester_id) template_data = dict( semester=semester, courses=courses, operation=operation, current_state_name=current_state_name, new_state_name=new_state_name, show_email_checkbox=operation in ['prepare', 'reenableEditorReview', 'startEvaluation', 'publish'] ) return render(request, "staff_course_operation.html", template_data)
def semester_course_operation(request, semester_id): semester = get_object_or_404(Semester, id=semester_id) raise_permission_denied_if_archived(semester) operation = request.GET.get("operation") if operation not in ["revertToNew", "prepare", "reenableEditorReview", "approve", "publish", "unpublish"]: messages.error(request, _("Unsupported operation: ") + str(operation)) return custom_redirect("staff:semester_view", semester_id) if request.method == "POST": course_ids = request.POST.getlist("course_ids") courses = Course.objects.filter(id__in=course_ids) if operation == "revertToNew": helper_semester_course_operation_revert(request, courses) elif operation == "prepare" or operation == "reenableEditorReview": helper_semester_course_operation_prepare(request, courses) elif operation == "approve": helper_semester_course_operation_approve(request, courses) elif operation == "publish": helper_semester_course_operation_publish(request, courses) elif operation == "unpublish": helper_semester_course_operation_unpublish(request, courses) return custom_redirect("staff:semester_view", semester_id) course_ids = request.GET.getlist("course") courses = Course.objects.filter(id__in=course_ids) if courses: current_state_name = STATES_ORDERED[courses[0].state] if operation == "revertToNew": new_state_name = STATES_ORDERED["new"] elif operation == "prepare" or operation == "reenableEditorReview": new_state_name = STATES_ORDERED["prepared"] elif operation == "approve": new_state_name = STATES_ORDERED["approved"] # remove courses without enough questionnaires courses_with_enough_questionnaires = [course for course in courses if course.has_enough_questionnaires()] difference = len(courses) - len(courses_with_enough_questionnaires) if difference: courses = courses_with_enough_questionnaires messages.warning( request, ungettext( "%(courses)d course can not be approved, because it has not enough questionnaires assigned. It was removed from the selection.", "%(courses)d courses can not be approved, because they have not enough questionnaires assigned. They were removed from the selection.", difference, ) % {"courses": difference}, ) elif operation == "publish": new_state_name = STATES_ORDERED["published"] elif operation == "unpublish": new_state_name = STATES_ORDERED["reviewed"] if not courses: messages.warning(request, _("Please select at least one course.")) return custom_redirect("staff:semester_view", semester_id) template_data = dict( semester=semester, courses=courses, operation=operation, current_state_name=current_state_name, new_state_name=new_state_name, ) return render(request, "staff_course_operation.html", template_data)
def semester_course_operation(request, semester_id): semester = get_object_or_404(Semester, id=semester_id) raise_permission_denied_if_archived(semester) operation = request.GET.get('operation') if operation not in [ 'revertToNew', 'prepare', 'reenableEditorReview', 'approve', 'publish', 'unpublish' ]: messages.error(request, _("Unsupported operation: ") + str(operation)) return custom_redirect('staff:semester_view', semester_id) if request.method == 'POST': course_ids = request.POST.getlist('course_ids') courses = Course.objects.filter(id__in=course_ids) send_email = request.POST.get('send_email') == 'on' if operation == 'revertToNew': helper_semester_course_operation_revert(request, courses) elif operation == 'prepare' or operation == 'reenableEditorReview': helper_semester_course_operation_prepare(request, courses, send_email) elif operation == 'approve': helper_semester_course_operation_approve(request, courses) elif operation == 'publish': helper_semester_course_operation_publish(request, courses, send_email) elif operation == 'unpublish': helper_semester_course_operation_unpublish(request, courses) return custom_redirect('staff:semester_view', semester_id) course_ids = request.GET.getlist('course') courses = Course.objects.filter(id__in=course_ids) if courses: current_state_name = STATES_ORDERED[courses[0].state] if operation == 'revertToNew': new_state_name = STATES_ORDERED['new'] elif operation == 'prepare' or operation == 'reenableEditorReview': new_state_name = STATES_ORDERED['prepared'] elif operation == 'approve': new_state_name = STATES_ORDERED['approved'] # remove courses without enough questionnaires courses_with_enough_questionnaires = [ course for course in courses if course.has_enough_questionnaires() ] difference = len(courses) - len(courses_with_enough_questionnaires) if difference: courses = courses_with_enough_questionnaires messages.warning( request, ungettext( "%(courses)d course can not be approved, because it has not enough questionnaires assigned. It was removed from the selection.", "%(courses)d courses can not be approved, because they have not enough questionnaires assigned. They were removed from the selection.", difference) % {'courses': difference}) elif operation == 'publish': new_state_name = STATES_ORDERED['published'] elif operation == 'unpublish': new_state_name = STATES_ORDERED['reviewed'] if not courses: messages.warning(request, _("Please select at least one course.")) return custom_redirect('staff:semester_view', semester_id) template_data = dict(semester=semester, courses=courses, operation=operation, current_state_name=current_state_name, new_state_name=new_state_name, show_email_checkbox=operation in ['prepare', 'reenableEditorReview', 'publish']) return render(request, "staff_course_operation.html", template_data)