Пример #1
0
def validate_markup(vctx, location, markup_str):
    # type: (ValidationContext, Text, Text) -> None

    def reverse_func(*args, **kwargs):
        pass

    from course.content import markup_to_html
    try:
        markup_to_html(
                course=None,
                repo=vctx.repo,
                commit_sha=vctx.commit_sha,
                text=markup_str,
                reverse_func=reverse_func,
                validate_only=True)
    except:
        from traceback import print_exc
        print_exc()

        tp, e, _ = sys.exc_info()

        assert tp is not None

        raise ValidationError(
                "%(location)s: %(err_type)s: %(err_str)s" % {
                    'location': location,
                    "err_type": tp.__name__,
                    "err_str": str(e)})
Пример #2
0
def validate_markup(vctx, location, markup_str):
    # type: (ValidationContext, Text, Text) -> None

    def reverse_func(*args, **kwargs):
        pass

    from course.content import markup_to_html
    try:
        markup_to_html(
                course=None,
                repo=vctx.repo,
                commit_sha=vctx.commit_sha,
                text=markup_str,
                reverse_func=reverse_func,
                validate_only=True)
    except:
        from traceback import print_exc
        print_exc()

        tp, e, _ = sys.exc_info()

        assert tp is not None

        raise ValidationError(
                "%(location)s: %(err_type)s: %(err_str)s" % {
                    'location': location,
                    "err_type": tp.__name__,
                    "err_str": str(e)})
Пример #3
0
    def process_choice_string(cls, page_context, s):
        s = remove_prefix(cls.CORRECT_TAG, s)
        s = markup_to_html(page_context, s)
        # allow HTML in option
        s = mark_safe(s)

        return s
Пример #4
0
    def grade(self, page_context, page_data, answer_data, grade_data):
        """This method is appropriate if the grade consists *only* of the
        feedback provided by humans. If more complicated/combined feedback
        is desired, a subclass would likely override this.
        """

        if answer_data is None:
            return AnswerFeedback(correctness=0,
                    feedback=ugettext("No answer provided."))

        if grade_data is None:
            return None

        if not grade_data["released"]:
            return None

        if grade_data["grade_percent"] is not None:
            correctness = grade_data["grade_percent"]/100
            feedback_text = "<p>%s</p>" % get_auto_feedback(correctness)

            if grade_data["feedback_text"]:
                feedback_text += (
                        string_concat(
                            "<p>",
                            _("The following feedback was provided"),
                            ":<p>")
                        + markup_to_html(
                            page_context, grade_data["feedback_text"]))

            return AnswerFeedback(
                    correctness=correctness,
                    feedback=feedback_text)
        else:
            return None
Пример #5
0
def validate_markup(ctx, location, markup_str):
    from course.content import markup_to_html
    try:
        markup_to_html(
                course=None,
                repo=ctx.repo,
                commit_sha=ctx.commit_sha,
                text=markup_str)
    except:
        from traceback import print_exc
        print_exc()

        tp, e, _ = sys.exc_info()

        raise ValidationError("%s: %s: %s" % (
            location, tp.__name__, str(e)))
Пример #6
0
    def grading_form_to_html(self, request, page_context, grading_form, grade_data):
        ctx = {"form": grading_form, "rubric": markup_to_html(page_context, self.page_desc.rubric)}

        from django.template import RequestContext
        from django.template.loader import render_to_string

        return render_to_string("course/human-feedback-form.html", RequestContext(request, ctx))
Пример #7
0
def markup_to_html(page_context, text):
    from course.content import markup_to_html

    return markup_to_html(
            page_context.course,
            page_context.repo,
            page_context.commit_sha,
            text)
Пример #8
0
def validate_markup(ctx, location, markup_str):
    def reverse_func(*args, **kwargs):
        pass

    from course.content import markup_to_html
    try:
        markup_to_html(course=None,
                       repo=ctx.repo,
                       commit_sha=ctx.commit_sha,
                       text=markup_str,
                       reverse_func=reverse_func,
                       validate_only=True)
    except:
        from traceback import print_exc
        print_exc()

        tp, e, _ = sys.exc_info()

        raise ValidationError("%s: %s: %s" % (location, tp.__name__, str(e)))
Пример #9
0
    def grading_form_to_html(self, request, page_context, grading_form, grade_data):
        ctx = {
                "form": grading_form,
                "rubric": markup_to_html(page_context, self.page_desc.rubric)
                }

        from django.template import RequestContext
        from django.template.loader import render_to_string
        return render_to_string(
                "course/human-feedback-form.html",
                RequestContext(request, ctx))
Пример #10
0
def validate_markup(ctx, location, markup_str):
    def reverse_func(*args, **kwargs):
        pass

    from course.content import markup_to_html
    try:
        markup_to_html(
                course=None,
                repo=ctx.repo,
                commit_sha=ctx.commit_sha,
                text=markup_str,
                reverse_func=reverse_func,
                validate_only=True)
    except:
        from traceback import print_exc
        print_exc()

        tp, e, _ = sys.exc_info()

        raise ValidationError("%s: %s: %s" % (
            location, tp.__name__, str(e)))
Пример #11
0
def view_markup_sandbox(pctx):
    if pctx.role not in [
            participation_role.instructor,
            participation_role.teaching_assistant
    ]:
        raise PermissionDenied(
            ugettext("must be instructor or TA to access sandbox"))

    request = pctx.request
    preview_text = ""

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    def make_form(data=None):
        help_text = (ugettext("Enter <a href=\"http://documen.tician.de/"
                              "relate/content.html#relate-markup\">"
                              "RELATE markup</a>."))
        return SandboxForm(None, "markdown", ustatus.editor_mode, help_text,
                           data)

    if request.method == "POST":
        form = make_form(request.POST)

        if form.is_valid():
            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(pctx.course, pctx.repo,
                                              pctx.course_commit_sha,
                                              form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(
                    pctx.request, messages.ERROR,
                    ugettext("Markup failed to render") + ": " +
                    "%(err_type)s: %(err_str)s" % {
                        "err_type": tp.__name__,
                        "err_str": e
                    })

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Пример #12
0
def view_markup_sandbox(pctx):
    if pctx.role not in [
            participation_role.instructor,
            participation_role.teaching_assistant]:
        raise PermissionDenied(
                ugettext("must be instructor or TA to access sandbox"))

    request = pctx.request
    preview_text = ""

    from course.models import get_user_status
    ustatus = get_user_status(request.user)

    def make_form(data=None):
        help_text = (ugettext("Enter <a href=\"http://documen.tician.de/"
                "relate/content.html#relate-markup\">"
                "RELATE markup</a>."))
        return SandboxForm(
                None, "markdown", ustatus.editor_mode,
                help_text,
                data)

    if request.method == "POST":
        form = make_form(request.POST)

        if form.is_valid():
            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(pctx.request, messages.ERROR,
                        ugettext("Markup failed to render")
                        + ": "
                        + "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__, "err_str": e})

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Пример #13
0
def view_markup_sandbox(pctx):
    request = pctx.request
    preview_text = ""

    def make_form(data=None):
        help_text = ("Enter <a href=\"http://documen.tician.de/"
                "relate/content.html#relate-markup\">"
                "RELATE markup</a>.")
        return SandboxForm(
                None, "markdown", vim_mode,
                help_text,
                data)

    vim_mode = pctx.request.session.get(CF_SANDBOX_VIM_MODE, False)

    if request.method == "POST":
        form = make_form(request.POST)

        if form.is_valid():
            pctx.request.session[CF_SANDBOX_VIM_MODE] = \
                    vim_mode = form.cleaned_data["vim_mode"]

            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(pctx.request, messages.ERROR,
                        "Markup failed to render: "
                        "%s: %s" % (tp.__name__, e))

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Пример #14
0
def view_markup_sandbox(pctx):
    if not pctx.has_permission(pperm.use_markup_sandbox):
        raise PermissionDenied()

    request = pctx.request
    preview_text = ""

    def make_form(data=None):
        help_text = (ugettext("Enter <a href=\"http://documen.tician.de/"
                              "relate/content.html#relate-markup\">"
                              "RELATE markup</a>."))
        return SandboxForm(None, "markdown", request.user.editor_mode,
                           help_text, data)

    if request.method == "POST" and "preview" in request.POST:
        form = make_form(request.POST)

        if form.is_valid():
            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(pctx.course, pctx.repo,
                                              pctx.course_commit_sha,
                                              form.cleaned_data["content"])
            except Exception:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(
                    pctx.request, messages.ERROR,
                    ugettext("Markup failed to render") + ": " +
                    "%(err_type)s: %(err_str)s" % {
                        "err_type": tp.__name__,
                        "err_str": e
                    })

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Пример #15
0
def view_markup_sandbox(pctx):
    request = pctx.request
    preview_text = ""

    def make_form(data=None):
        help_text = ("Enter <a href=\"http://documen.tician.de/"
                "courseflow/content.html#courseflow-markup\">"
                "CourseFlow markup</a>.")
        return SandboxForm(
                None, "markdown", vim_mode,
                help_text,
                data)

    vim_mode = pctx.request.session.get(CF_SANDBOX_VIM_MODE, False)

    if request.method == "POST":
        form = make_form(request.POST)

        if form.is_valid():
            pctx.request.session[CF_SANDBOX_VIM_MODE] = \
                    vim_mode = form.cleaned_data["vim_mode"]

            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(pctx.request, messages.ERROR,
                        "Markup failed to render: "
                        "%s: %s" % (tp.__name__, e))

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Пример #16
0
def view_markup_sandbox(pctx):
    if not pctx.has_permission(pperm.use_markup_sandbox):
        raise PermissionDenied()

    request = pctx.request
    preview_text = ""

    def make_form(data=None):
        help_text = (ugettext("Enter <a href=\"http://documen.tician.de/"
                "relate/content.html#relate-markup\">"
                "RELATE markup</a>."))
        return SandboxForm(
                None, "markdown", request.user.editor_mode,
                help_text,
                data)

    if request.method == "POST" and "preview" in request.POST:
        form = make_form(request.POST)

        if form.is_valid():
            from course.content import markup_to_html
            try:
                preview_text = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        form.cleaned_data["content"])
            except:
                import sys
                tp, e, _ = sys.exc_info()

                messages.add_message(pctx.request, messages.ERROR,
                        ugettext("Markup failed to render")
                        + ": "
                        + "%(err_type)s: %(err_str)s" % {
                            "err_type": tp.__name__, "err_str": e})

        form = make_form(request.POST)

    else:
        form = make_form()

    return render_course_page(pctx, "course/sandbox-markup.html", {
        "form": form,
        "preview_text": preview_text,
    })
Пример #17
0
def view_calendar(pctx):
    from course.content import markup_to_html

    events_json = []

    from course.content import get_raw_yaml_from_repo
    try:
        event_descr = get_raw_yaml_from_repo(pctx.repo,
                                             pctx.course.events_file,
                                             pctx.course_commit_sha)
    except ObjectDoesNotExist:
        event_descr = {}

    event_kinds_desc = event_descr.get("event_kinds", {})
    event_info_desc = event_descr.get("events", {})

    event_info_list = []

    for event in (Event.objects.filter(
            course=pctx.course, shown_in_calendar=True).order_by("time")):
        kind_desc = event_kinds_desc.get(event.kind)

        human_title = unicode(event)

        event_json = {
            "id": event.id,
            "start": event.time.isoformat(),
            "allDay": event.all_day,
        }
        if event.end_time is not None:
            event_json["end"] = event.end_time.isoformat()

        if kind_desc is not None:
            if "color" in kind_desc:
                event_json["color"] = kind_desc["color"]
            if "title" in kind_desc:
                if event.ordinal is not None:
                    human_title = kind_desc["title"].format(nr=event.ordinal)
                else:
                    human_title = kind_desc["title"]

        description = None
        event_desc = event_info_desc.get(unicode(event))
        if event_desc is not None:
            if "description" in event_desc:
                description = markup_to_html(pctx.course, pctx.repo,
                                             pctx.course_commit_sha,
                                             event_desc["description"])

            if "title" in event_desc:
                human_title = event_desc["title"]

            if "color" in event_desc:
                human_title = event_desc["color"]

        event_json["title"] = human_title

        if description:
            event_json["url"] = "#event-%d" % event.id

            start_time = event.time
            end_time = event.end_time

            if event.all_day:
                start_time = start_time.date()
                end_time = end_time.date()

            event_info_list.append(
                EventInfo(id=event.id,
                          human_title=human_title,
                          start_time=start_time,
                          end_time=end_time,
                          description=description))

        events_json.append(event_json)

    from json import dumps
    return render_course_page(pctx, "course/calendar.html", {
        "events_json": dumps(events_json),
        "event_info_list": event_info_list,
    })
Пример #18
0
def view_calendar(pctx):
    from course.content import markup_to_html

    events_json = []

    from course.content import get_yaml_from_repo_as_dict
    try:
        event_descr = get_yaml_from_repo_as_dict(pctx.repo,
                pctx.course.events_file, pctx.course_commit_sha)
    except ObjectDoesNotExist:
        event_descr = {}
        print "ODN"

    event_kinds_desc = event_descr.get("event_kinds", {})
    event_info_desc = event_descr.get("events", {})

    event_info_list = []

    for event in Event.objects.order_by("time"):
        kind_desc = event_kinds_desc.get(event.kind)

        human_title = unicode(event)

        event_json = {
                "id": event.id,
                "start": event.time.isoformat(),
                }
        if event.end_time is not None:
            event_json["end"] = event.end_time.isoformat()

        if kind_desc is not None:
            if "color" in kind_desc:
                event_json["color"] = kind_desc["color"]
            if "title" in kind_desc:
                if event.ordinal:
                    human_title = kind_desc["title"].format(nr=event.ordinal)
                else:
                    human_title = kind_desc["title"]

        description = None
        event_desc = event_info_desc.get(unicode(event))
        if event_desc is not None:
            if "description" in event_desc:
                description = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        event_desc["description"])

            if "title" in event_desc:
                human_title = event_desc["title"]

            if "color" in event_desc:
                human_title = event_desc["color"]

        event_json["title"] = human_title

        if description:
            event_json["url"] = "#event-%d" % event.id
            event_info_list.append(
                    EventInfo(
                        id=event.id,
                        human_title=human_title,
                        start_time=event.time,
                        end_time=event.end_time,
                        description=description
                        ))

        events_json.append(event_json)

    from json import dumps
    return render_course_page(pctx, "course/calendar.html", {
        "events_json": dumps(events_json),
        "event_info_list": event_info_list,
    })
Пример #19
0
def view_calendar(pctx):
    from course.content import markup_to_html

    events_json = []

    from course.content import get_raw_yaml_from_repo
    try:
        event_descr = get_raw_yaml_from_repo(pctx.repo,
                pctx.course.events_file, pctx.course_commit_sha)
    except ObjectDoesNotExist:
        event_descr = {}

    event_kinds_desc = event_descr.get("event_kinds", {})
    event_info_desc = event_descr.get("events", {})

    event_info_list = []

    for event in (Event.objects
            .filter(
                course=pctx.course,
                shown_in_calendar=True)
            .order_by("-time")):
        kind_desc = event_kinds_desc.get(event.kind)

        human_title = six.text_type(event)

        event_json = {
                "id": event.id,
                "start": event.time.isoformat(),
                "allDay": event.all_day,
                }
        if event.end_time is not None:
            event_json["end"] = event.end_time.isoformat()

        if kind_desc is not None:
            if "color" in kind_desc:
                event_json["color"] = kind_desc["color"]
            if "title" in kind_desc:
                if event.ordinal is not None:
                    human_title = kind_desc["title"].format(nr=event.ordinal)
                else:
                    human_title = kind_desc["title"]

        description = None
        event_desc = event_info_desc.get(six.text_type(event))
        if event_desc is not None:
            if "description" in event_desc:
                description = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        event_desc["description"])

            if "title" in event_desc:
                human_title = event_desc["title"]

            if "color" in event_desc:
                event_json["color"] = event_desc["color"]

        event_json["title"] = human_title

        if description:
            event_json["url"] = "#event-%d" % event.id

            start_time = event.time
            end_time = event.end_time

            if event.all_day:
                start_time = start_time.date()
                end_time = end_time.date()

            event_info_list.append(
                    EventInfo(
                        id=event.id,
                        human_title=human_title,
                        start_time=start_time,
                        end_time=end_time,
                        description=description
                        ))

        events_json.append(event_json)

    from course.views import get_now_or_fake_time
    default_date = get_now_or_fake_time(pctx.request).date()
    if pctx.course.end_date is not None and default_date > pctx.course.end_date:
        default_date = pctx.course.end_date

    from json import dumps
    return render_course_page(pctx, "course/calendar.html", {
        "events_json": dumps(events_json),
        "event_info_list": event_info_list,
        "default_date": default_date.isoformat(),
    })
Пример #20
0
 def correct_answer(self, page_context, page_data, answer_data, grade_data):
     if hasattr(self.page_desc, "correct_answer"):
         return markup_to_html(page_context, self.page_desc.correct_answer)
     else:
         return None
Пример #21
0
def finish_flow_session_view(request, course_identifier, flow_identifier):
    flow_session = find_current_flow_session(request, flow_identifier)

    if flow_session is None:
        messages.add_message(request, messages.WARNING,
                "No session record found for this flow. "
                "Redirected to flow start page.")

        return redirect("course.flow.start_flow",
                course_identifier,
                flow_identifier)

    fctx = FlowContext(request, course_identifier, flow_identifier,
            flow_session=flow_session)

    answer_visits = assemble_answer_visits(flow_session)

    from course.content import markup_to_html
    completion_text = markup_to_html(
            fctx.course, fctx.repo, fctx.flow_commit_sha,
            fctx.flow_desc.completion_text)

    (answered_count, unanswered_count) = count_answered(
            fctx, fctx.flow_session, answer_visits)

    def render_finish_response(template, **kwargs):
        render_args = {
            "course": fctx.course,
            "course_desc": fctx.course_desc,
            "flow_identifier": fctx.flow_identifier,
            "flow_desc": fctx.flow_desc,
            "participation": fctx.participation,
            "role": fctx.role,
            "participation_role": participation_role,
        }

        render_args.update(kwargs)
        return render(request, template, render_args)

    if request.method == "POST":
        if "submit" not in request.POST:
            raise SuspiciousOperation("odd POST parameters")

        if not flow_session.in_progress:
            raise PermissionDenied("Can't end a session that's already ended")

        # Actually end the flow session

        request.session["flow_session_id"] = None

        grade_info = finish_flow_session(fctx, flow_session)

        if answered_count + unanswered_count:
            # This is a graded flow.

            if grade_info is None:
                messages.add_message(request, messages.INFO,
                        "A grade for your work has not yet been assigned. "
                        "Please check back later for grade information.")

                return render_finish_response(
                        "course/flow-completion.html",
                        last_page_nr=None,
                        completion_text=completion_text)

            return render_finish_response(
                    "course/flow-completion-grade.html",
                    completion_text=completion_text,
                    grade_info=grade_info)

        else:
            # {{{ no grade

            return render_finish_response(
                    "course/flow-completion.html",
                    last_page_nr=None,
                    completion_text=completion_text)

            # }}}

    if (answered_count + unanswered_count == 0
            and fctx.flow_commit_sha == fctx.course_commit_sha):
        # Not serious--no questions in flow, and no new version available.
        # No need to end the flow visit.

        return render_finish_response(
                "course/flow-completion.html",
                last_page_nr=fctx.page_count-1,
                completion_text=completion_text)

    elif not flow_session.in_progress:
        # Just reviewing: re-show grades.
        grade_info = gather_grade_info(fctx, answer_visits)

        return render_finish_response(
                "course/flow-completion-grade.html",
                completion_text=completion_text,
                grade_info=grade_info)

    else:
        # confirm ending flow
        return render_finish_response(
                "course/flow-confirm-completion.html",
                last_page_nr=fctx.page_count-1,
                answered_count=answered_count,
                unanswered_count=unanswered_count,
                total_count=answered_count+unanswered_count)
Пример #22
0
def finish_flow_session_view(pctx, flow_session_id):
    now_datetime = get_now_or_fake_time(pctx.request)

    request = pctx.request

    flow_session_id = int(flow_session_id)
    flow_session = get_and_check_flow_session(pctx, flow_session_id)
    flow_id = flow_session.flow_id

    fctx = FlowContext(pctx.repo, pctx.course, flow_id, participation=pctx.participation, flow_session=flow_session)

    access_rule = get_session_access_rule(flow_session, pctx.role, fctx.flow_desc, now_datetime, pctx.remote_address)

    answer_visits = assemble_answer_visits(flow_session)

    from course.content import markup_to_html

    completion_text = markup_to_html(fctx.course, fctx.repo, pctx.course_commit_sha, fctx.flow_desc.completion_text)

    (answered_count, unanswered_count) = count_answered_gradable(fctx, flow_session, answer_visits)
    is_graded_flow = bool(answered_count + unanswered_count)

    if flow_permission.view not in access_rule.permissions:
        raise PermissionDenied()

    def render_finish_response(template, **kwargs):
        render_args = {"flow_identifier": fctx.flow_id, "flow_desc": fctx.flow_desc}

        render_args.update(kwargs)
        return render_course_page(pctx, template, render_args, allow_instant_flow_requests=False)

    if request.method == "POST":
        if "submit" not in request.POST:
            raise SuspiciousOperation(_("odd POST parameters"))

        if not flow_session.in_progress:
            raise PermissionDenied(_("Can't end a session that's already ended"))

        if flow_permission.end_session not in access_rule.permissions:
            raise PermissionDenied(_("not permitted to end session"))

        grading_rule = get_session_grading_rule(flow_session, pctx.role, fctx.flow_desc, now_datetime)
        grade_info = finish_flow_session(fctx, flow_session, grading_rule, now_datetime=now_datetime)

        if is_graded_flow:
            return render_finish_response(
                "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info
            )

        else:
            return render_finish_response(
                "course/flow-completion.html",
                last_page_nr=None,
                flow_session=flow_session,
                completion_text=completion_text,
            )

    if not is_graded_flow or (flow_session.in_progress and flow_permission.end_session not in access_rule.permissions):
        # No ability to end--just show completion page.

        return render_finish_response(
            "course/flow-completion.html",
            last_page_nr=flow_session.page_count - 1,
            flow_session=flow_session,
            completion_text=completion_text,
        )

    elif not flow_session.in_progress:
        # Just reviewing: re-show grades.
        grade_info = gather_grade_info(fctx, flow_session, answer_visits)

        return render_finish_response(
            "course/flow-completion-grade.html", completion_text=completion_text, grade_info=grade_info
        )

    else:
        # confirm ending flow
        return render_finish_response(
            "course/flow-confirm-completion.html",
            last_page_nr=flow_session.page_count - 1,
            flow_session=flow_session,
            answered_count=answered_count,
            unanswered_count=unanswered_count,
            total_count=answered_count + unanswered_count,
        )
Пример #23
0
def view_calendar(pctx):
    from course.content import markup_to_html, parse_date_spec

    from course.views import get_now_or_fake_time
    now = get_now_or_fake_time(pctx.request)

    if not pctx.has_permission(pperm.view_calendar):
        raise PermissionDenied(_("may not view calendar"))

    events_json = []

    from course.content import get_raw_yaml_from_repo
    try:
        event_descr = get_raw_yaml_from_repo(pctx.repo,
                pctx.course.events_file, pctx.course_commit_sha)
    except ObjectDoesNotExist:
        event_descr = {}

    event_kinds_desc = event_descr.get("event_kinds", {})
    event_info_desc = event_descr.get("events", {})

    event_info_list = []

    events = sorted(
            Event.objects
            .filter(
                course=pctx.course,
                shown_in_calendar=True),
            key=lambda evt: (
                -evt.time.year, -evt.time.month, -evt.time.day,
                evt.time.hour, evt.time.minute, evt.time.second))

    for event in events:
        kind_desc = event_kinds_desc.get(event.kind)

        human_title = six.text_type(event)

        event_json = {
                "id": event.id,
                "start": event.time.isoformat(),
                "allDay": event.all_day,
                }
        if event.end_time is not None:
            event_json["end"] = event.end_time.isoformat()

        if kind_desc is not None:
            if "color" in kind_desc:
                event_json["color"] = kind_desc["color"]
            if "title" in kind_desc:
                if event.ordinal is not None:
                    human_title = kind_desc["title"].format(nr=event.ordinal)
                else:
                    human_title = kind_desc["title"]

        description = None
        show_description = True
        event_desc = event_info_desc.get(six.text_type(event))
        if event_desc is not None:
            if "description" in event_desc:
                description = markup_to_html(
                        pctx.course, pctx.repo, pctx.course_commit_sha,
                        event_desc["description"])

            if "title" in event_desc:
                human_title = event_desc["title"]

            if "color" in event_desc:
                event_json["color"] = event_desc["color"]

            if "show_description_from" in event_desc:
                ds = parse_date_spec(
                        pctx.course, event_desc["show_description_from"])
                if now < ds:
                    show_description = False

            if "show_description_until" in event_desc:
                ds = parse_date_spec(
                        pctx.course, event_desc["show_description_until"])
                if now > ds:
                    show_description = False

        event_json["title"] = human_title

        if show_description and description:
            event_json["url"] = "#event-%d" % event.id

            start_time = event.time
            end_time = event.end_time

            if event.all_day:
                start_time = start_time.date()
                if end_time is not None:
                    local_end_time = as_local_time(end_time)
                    end_midnight = datetime.time(tzinfo=local_end_time.tzinfo)
                    if local_end_time.time() == end_midnight:
                        end_time = (end_time - datetime.timedelta(days=1)).date()
                    else:
                        end_time = end_time.date()

            event_info_list.append(
                    EventInfo(
                        id=event.id,
                        human_title=human_title,
                        start_time=start_time,
                        end_time=end_time,
                        description=description
                        ))

        events_json.append(event_json)

    default_date = now.date()
    if pctx.course.end_date is not None and default_date > pctx.course.end_date:
        default_date = pctx.course.end_date

    from json import dumps
    return render_course_page(pctx, "course/calendar.html", {
        "events_json": dumps(events_json),
        "event_info_list": event_info_list,
        "default_date": default_date.isoformat(),
    })
Пример #24
0
def batch_issue_exam_tickets(pctx):
    if pctx.role not in [
            participation_role.instructor,
            ]:
        raise PermissionDenied(
                _("must be instructor or TA to batch-issue tickets"))

    form_text = ""

    request = pctx.request
    if request.method == "POST":
        form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode,
                request.POST)

        if form.is_valid():
            exam = form.cleaned_data["exam"]

            from jinja2 import TemplateSyntaxError
            from course.content import markup_to_html
            try:
                with transaction.atomic():
                    if form.cleaned_data["revoke_prior"]:
                        ExamTicket.objects.filter(
                                exam=exam,
                                state__in=(
                                    exam_ticket_states.valid,
                                    exam_ticket_states.used,
                                    )
                                ).update(state=exam_ticket_states.revoked)

                    tickets = []
                    for participation in (
                            Participation.objects.filter(
                                course=pctx.course,
                                status=participation_status.active)
                            .order_by("user__last_name")
                            ):
                        ticket = ExamTicket()
                        ticket.exam = exam
                        ticket.participation = participation
                        ticket.creator = request.user
                        ticket.state = exam_ticket_states.valid
                        ticket.code = gen_ticket_code()
                        ticket.save()

                        tickets.append(ticket)

                    checkin_uri = pctx.request.build_absolute_uri(
                            reverse("relate-check_in_for_exam"))
                    form_text = markup_to_html(
                            pctx.course, pctx.repo, pctx.course_commit_sha,
                            form.cleaned_data["format"], jinja_env={
                                    "tickets": tickets,
                                    "checkin_uri": checkin_uri,
                                    })
            except TemplateSyntaxError as e:
                messages.add_message(request, messages.ERROR,
                    string_concat(
                        _("Template rendering failed"),
                        ": line %(lineno)d: %(err_str)s")
                    % {
                        "lineno": e.lineno,
                        "err_str": e.message.decode("utf-8")})
            except Exception as e:
                messages.add_message(request, messages.ERROR,
                    string_concat(
                        _("Template rendering failed"),
                        ": %(err_type)s: %(err_str)s")
                    % {"err_type": type(e).__name__,
                        "err_str": str(e)})
            else:
                messages.add_message(request, messages.SUCCESS,
                        _("%d tickets issued.") % len(tickets))

    else:
        form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode)

    return render_course_page(pctx, "course/batch-exam-tickets-form.html", {
        "form": form,
        "form_text": form_text,
        "form_description": ugettext("Batch-Issue Exam Tickets")
        })
Пример #25
0
def batch_issue_exam_tickets(pctx):
    if not pctx.has_permission(pperm.batch_issue_exam_ticket):
        raise PermissionDenied(_("may not batch-issue tickets"))

    form_text = ""

    request = pctx.request
    if request.method == "POST":
        form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode,
                                     request.POST)

        if form.is_valid():
            exam = form.cleaned_data["exam"]

            from jinja2 import TemplateSyntaxError
            from course.content import markup_to_html
            try:
                with transaction.atomic():
                    if form.cleaned_data["revoke_prior"]:
                        ExamTicket.objects.filter(
                            exam=exam,
                            state__in=(
                                exam_ticket_states.valid,
                                exam_ticket_states.used,
                            )).update(state=exam_ticket_states.revoked)

                    tickets = []
                    for participation in (Participation.objects.filter(
                            course=pctx.course,
                            status=participation_status.active).order_by(
                                "user__last_name")):
                        ticket = ExamTicket()
                        ticket.exam = exam
                        ticket.participation = participation
                        ticket.creator = request.user
                        ticket.state = exam_ticket_states.valid
                        ticket.code = gen_ticket_code()
                        ticket.valid_start_time = \
                                form.cleaned_data["valid_start_time"]
                        ticket.valid_end_time = form.cleaned_data[
                            "valid_end_time"]
                        ticket.restrict_to_facility = \
                                form.cleaned_data["restrict_to_facility"]
                        ticket.save()

                        tickets.append(ticket)

                    checkin_uri = pctx.request.build_absolute_uri(
                        reverse("relate-check_in_for_exam"))
                    form_text = markup_to_html(pctx.course,
                                               pctx.repo,
                                               pctx.course_commit_sha,
                                               form.cleaned_data["format"],
                                               jinja_env={
                                                   "tickets": tickets,
                                                   "checkin_uri": checkin_uri,
                                               })
            except TemplateSyntaxError as e:
                messages.add_message(
                    request, messages.ERROR,
                    string_concat(_("Template rendering failed"),
                                  ": line %(lineno)d: %(err_str)s") % {
                                      "lineno": e.lineno,
                                      "err_str": e.message.decode("utf-8")
                                  })
            except Exception as e:
                messages.add_message(
                    request, messages.ERROR,
                    string_concat(_("Template rendering failed"),
                                  ": %(err_type)s: %(err_str)s") % {
                                      "err_type": type(e).__name__,
                                      "err_str": str(e)
                                  })
            else:
                messages.add_message(request, messages.SUCCESS,
                                     _("%d tickets issued.") % len(tickets))

    else:
        form = BatchIssueTicketsForm(pctx.course, request.user.editor_mode)

    return render_course_page(
        pctx, "course/batch-exam-tickets-form.html", {
            "form": form,
            "form_text": form_text,
            "form_description": gettext("Batch-Issue Exam Tickets")
        })
Пример #26
0
def finish_flow_session_view(pctx, flow_identifier):
    request = pctx.request

    flow_session = find_current_flow_session(
            request, pctx.course, flow_identifier)

    if flow_session is None:
        messages.add_message(request, messages.WARNING,
                "No session record found for this flow. "
                "Redirected to flow start page.")

        return redirect("course.flow.start_flow",
                pctx.course.identifier,
                flow_identifier)

    fctx = FlowContext(pctx.repo, pctx.course, flow_identifier,
            participation=pctx.participation,
            flow_session=flow_session)

    current_access_rule = fctx.get_current_access_rule(
            flow_session, pctx.role, pctx.participation,
            get_now_or_fake_time(request))

    answer_visits = assemble_answer_visits(flow_session)

    from course.content import markup_to_html
    completion_text = markup_to_html(
            fctx.course, fctx.repo, fctx.flow_commit_sha,
            fctx.flow_desc.completion_text)

    (answered_count, unanswered_count) = count_answered(
            fctx, flow_session, answer_visits)
    is_graded_flow = bool(answered_count + unanswered_count)

    if flow_permission.view not in current_access_rule.permissions:
        raise PermissionDenied()

    def render_finish_response(template, **kwargs):
        render_args = {
            "flow_identifier": fctx.flow_identifier,
            "flow_desc": fctx.flow_desc,
        }

        render_args.update(kwargs)
        return render_course_page(
                pctx, template, render_args,
                allow_instant_flow_requests=False)

    if request.method == "POST":
        if "submit" not in request.POST:
            raise SuspiciousOperation("odd POST parameters")

        if not flow_session.in_progress:
            raise PermissionDenied("Can't end a session that's already ended")

        # Actually end the flow session
        request.session["flow_session_id"] = None

        grade_info = finish_flow_session(fctx, flow_session, current_access_rule)

        if is_graded_flow:
            return render_finish_response(
                    "course/flow-completion-grade.html",
                    completion_text=completion_text,
                    grade_info=grade_info)

        else:
            return render_finish_response(
                    "course/flow-completion.html",
                    last_page_nr=None,
                    completion_text=completion_text)

            # }}}

    if (not is_graded_flow
            and fctx.flow_commit_sha == fctx.course_commit_sha):
        # Not serious--no questions in flow, and no new version available.
        # No need to end the flow visit.

        return render_finish_response(
                "course/flow-completion.html",
                last_page_nr=flow_session.page_count-1,
                completion_text=completion_text)

    elif not flow_session.in_progress:
        # Just reviewing: re-show grades.
        grade_info = gather_grade_info(flow_session, answer_visits)

        return render_finish_response(
                "course/flow-completion-grade.html",
                completion_text=completion_text,
                grade_info=grade_info)

    else:
        # confirm ending flow
        return render_finish_response(
                "course/flow-confirm-completion.html",
                last_page_nr=flow_session.page_count-1,
                answered_count=answered_count,
                unanswered_count=unanswered_count,
                total_count=answered_count+unanswered_count)
Пример #27
0
 def body(self, page_context, page_data):
     return markup_to_html(page_context, self.page_desc.prompt)
Пример #28
0
def view_calendar(pctx):
    from course.content import markup_to_html, parse_date_spec

    from course.views import get_now_or_fake_time

    now = get_now_or_fake_time(pctx.request)

    if not pctx.has_permission(pperm.view_calendar):
        raise PermissionDenied(_("may not view calendar"))

    events_json = []

    from course.content import get_raw_yaml_from_repo

    try:
        event_descr = get_raw_yaml_from_repo(pctx.repo, pctx.course.events_file, pctx.course_commit_sha)
    except ObjectDoesNotExist:
        event_descr = {}

    event_kinds_desc = event_descr.get("event_kinds", {})
    event_info_desc = event_descr.get("events", {})

    event_info_list = []

    for event in Event.objects.filter(course=pctx.course, shown_in_calendar=True).order_by("-time"):
        kind_desc = event_kinds_desc.get(event.kind)

        human_title = six.text_type(event)

        event_json = {"id": event.id, "start": event.time.isoformat(), "allDay": event.all_day}
        if event.end_time is not None:
            event_json["end"] = event.end_time.isoformat()

        if kind_desc is not None:
            if "color" in kind_desc:
                event_json["color"] = kind_desc["color"]
            if "title" in kind_desc:
                if event.ordinal is not None:
                    human_title = kind_desc["title"].format(nr=event.ordinal)
                else:
                    human_title = kind_desc["title"]

        description = None
        show_description = True
        event_desc = event_info_desc.get(six.text_type(event))
        if event_desc is not None:
            if "description" in event_desc:
                description = markup_to_html(pctx.course, pctx.repo, pctx.course_commit_sha, event_desc["description"])

            if "title" in event_desc:
                human_title = event_desc["title"]

            if "color" in event_desc:
                event_json["color"] = event_desc["color"]

            if "show_description_from" in event_desc:
                ds = parse_date_spec(pctx.course, event_desc["show_description_from"])
                if now < ds:
                    show_description = False

            if "show_description_until" in event_desc:
                ds = parse_date_spec(pctx.course, event_desc["show_description_until"])
                if now > ds:
                    show_description = False

        event_json["title"] = human_title

        if show_description and description:
            event_json["url"] = "#event-%d" % event.id

            start_time = event.time
            end_time = event.end_time

            if event.all_day:
                start_time = start_time.date()
                local_end_time = as_local_time(end_time)
                end_midnight = datetime.time(tzinfo=local_end_time.tzinfo)
                if local_end_time.time() == end_midnight:
                    end_time = (end_time - datetime.timedelta(days=1)).date()
                else:
                    end_time = end_time.date()

            event_info_list.append(
                EventInfo(
                    id=event.id,
                    human_title=human_title,
                    start_time=start_time,
                    end_time=end_time,
                    description=description,
                )
            )

        events_json.append(event_json)

    default_date = now.date()
    if pctx.course.end_date is not None and default_date > pctx.course.end_date:
        default_date = pctx.course.end_date

    from json import dumps

    return render_course_page(
        pctx,
        "course/calendar.html",
        {
            "events_json": dumps(events_json),
            "event_info_list": event_info_list,
            "default_date": default_date.isoformat(),
        },
    )