Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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))
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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))
Ejemplo n.º 5
0
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))
Ejemplo n.º 6
0
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))
Ejemplo n.º 7
0
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))
Ejemplo n.º 8
0
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))
Ejemplo n.º 9
0
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))
Ejemplo n.º 10
0
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))
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
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))
Ejemplo n.º 13
0
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))
Ejemplo n.º 14
0
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))
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
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))
Ejemplo n.º 17
0
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))
Ejemplo n.º 18
0
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)
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
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)
Ejemplo n.º 23
0
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)