Ejemplo n.º 1
0
def ical(request, year, semester_type, slug, ical_type=None):
    resources = [_(u'lectures'), _(u'exams')]
    if ical_type and ical_type not in resources:
        raise http.Http404
    elif ical_type:
        resources = [ical_type]

    # TODO(adamcik): Add a last modified header and return 304s?

    title = urlresolvers.reverse('schedule', args=[year, semester_type, slug])
    hostname = (settings.TIMETABLE_HOSTNAME
                or request.META.get('HTTP_HOST', socket.getfqdn()))

    semester = Semester(year=year, type=semester_type)

    cal = vobject.iCalendar()
    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this

    # TODO(adamcik): use same logic as in common.templatetags.title
    if slug.lower().endswith('s'):
        description = _(
            u"%(slug)s' %(semester)s %(year)s schedule for %(resources)s")
    else:
        description = _(
            u"%(slug)s's %(semester)s %(year)s schedule for %(resources)s")

    cal.add('X-WR-CALNAME').value = title.strip('/')
    cal.add('X-WR-CALDESC').value = description % {
        'slug': slug,
        'semester': semester.get_type_display(),
        'year': semester.year,
        'resources': ', '.join(resources),
    }

    if _('lectures') in resources:
        lectures = Lecture.objects.get_lectures(year, semester.type, slug)
        add_lectutures(lectures, semester.year, cal, hostname)

    if _('exams') in resources:
        exams = Exam.objects.get_exams(year, semester.type, slug)
        add_exams(exams, cal, hostname)

    icalstream = cal.serialize()

    filename = '%s.ics' % '-'.join([str(semester.year), semester.type, slug] +
                                   resources)

    response = http.HttpResponse(icalstream, content_type='text/calendar')
    response['Content-Type'] = 'text/calendar; charset=utf-8'
    response['Filename'] = filename  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=%s' % filename
    response['X-Robots-Tag'] = 'noindex, nofollow'

    # TODO(adamcik): add expires header that reduces load on old semesters

    return response
Ejemplo n.º 2
0
def select_groups(request, year, semester_type, slug):
    '''Form handler for selecting groups to use in schedule'''
    courses = Course.objects.get_courses(year, semester_type, slug)
    course_groups = Course.get_groups(year, semester_type,
                                      [c.id for c in courses])

    if request.method == 'POST':
        with transaction.atomic():
            for c in courses:
                try:
                    groups = course_groups[c.id]
                except KeyError:  # Skip courses without groups
                    continue

                group_form = forms.GroupForm(groups, request.POST, prefix=c.id)

                if group_form.is_valid():
                    subscription = Subscription.objects.get_subscriptions(
                        year, semester_type, slug).get(course=c)

                    subscription.groups = group_form.cleaned_data['groups']

            return shortcuts.redirect('schedule-advanced', year,
                                      Semester.localize(semester_type), slug)

    color_map = utils.ColorMap(hex=True)
    subscription_groups = Subscription.get_groups(year, semester_type, slug)
    all_subscripted_groups = set()

    for groups in subscription_groups.values():
        for group in groups:
            all_subscripted_groups.add(group)

    for c in courses:
        color_map[c.id]
        subscription_id = c.subscription_set.get(student__slug=slug).pk

        try:
            groups = course_groups[c.id]
        except KeyError:  # Skip courses without groups
            continue

        initial_groups = subscription_groups.get(subscription_id,
                                                 all_subscripted_groups)

        c.group_form = forms.GroupForm(groups,
                                       prefix=c.id,
                                       initial={'groups': initial_groups})

    return shortcuts.render(
        request, 'select_groups.html', {
            'semester': Semester(year=year, type=semester_type),
            'slug': slug,
            'courses': courses,
            'color_map': color_map,
        })
Ejemplo n.º 3
0
def ical(request, year, semester_type, slug, ical_type=None):
    resources = [_(u'lectures'), _(u'exams')]
    if ical_type and ical_type not in resources:
        raise http.Http404
    elif ical_type:
        resources = [ical_type]

    title  = urlresolvers.reverse('schedule', args=[year, semester_type, slug])
    hostname = (settings.TIMETABLE_HOSTNAME or
                request.META.get('HTTP_HOST', socket.getfqdn()))

    semester = Semester(year=year, type=semester_type)

    cal = vobject.iCalendar()
    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this

    # TODO(adamcik): use same logic as in common.templatetags.title
    if slug.lower().endswith('s'):
        description = _(u"%(slug)s' %(semester)s %(year)s schedule for %(resources)s")
    else:
        description = _(u"%(slug)s's %(semester)s %(year)s schedule for %(resources)s")

    cal.add('X-WR-CALNAME').value = title.strip('/')
    cal.add('X-WR-CALDESC').value = description % {
        'slug': slug,
        'semester': semester.get_type_display(),
        'year': semester.year,
        'resources': ', '.join(resources),
    }

    if _('lectures') in resources:
        lectures = Lecture.objects.get_lectures(year, semester.type, slug)
        add_lectutures(lectures, semester.year, cal, hostname)

    if _('exams') in resources:
        exams = Exam.objects.get_exams(year, semester.type, slug)
        add_exams(exams, cal, hostname)

    icalstream = cal.serialize()

    filename = '%s.ics' % '-'.join([str(semester.year), semester.type, slug] + resources)

    response = http.HttpResponse(icalstream, content_type='text/calendar')
    response['Content-Type'] = 'text/calendar; charset=utf-8'
    response['Filename'] = filename  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=%s' % filename
    response['X-Robots-Tag'] = 'noindex, nofollow'

    # TODO(adamcik): add expires header that reduces load on old semesters

    return response
Ejemplo n.º 4
0
def ical(request, year, semester_type, slug, ical_type=None):
    resources = [_(u"lectures"), _(u"exams")]
    if ical_type and ical_type not in resources:
        raise http.Http404
    elif ical_type:
        resources = [ical_type]

    title = urlresolvers.reverse("schedule", args=[year, semester_type, slug])
    hostname = settings.TIMETABLE_HOSTNAME or request.META.get("HTTP_HOST", socket.getfqdn())

    semester = Semester(year=year, type=semester_type)

    cal = vobject.iCalendar()
    cal.add("method").value = "PUBLISH"  # IE/Outlook needs this

    # TODO(adamcik): use same logic as in common.templatetags.title
    if slug.lower().endswith("s"):
        description = _(u"%(slug)s' %(semester)s %(year)s schedule for %(resources)s")
    else:
        description = _(u"%(slug)s's %(semester)s %(year)s schedule for %(resources)s")

    cal.add("X-WR-CALNAME").value = title.strip("/")
    cal.add("X-WR-CALDESC").value = description % {
        "slug": slug,
        "semester": semester.get_type_display(),
        "year": semester.year,
        "resources": ", ".join(resources),
    }

    if _("lectures") in resources:
        lectures = Lecture.objects.get_lectures(year, semester.type, slug)
        add_lectutures(lectures, semester.year, cal, hostname)

    if _("exams") in resources:
        exams = Exam.objects.get_exams(year, semester.type, slug)
        add_exams(exams, cal, hostname)

    icalstream = cal.serialize()

    filename = "%s.ics" % "-".join([str(semester.year), semester.type, slug] + resources)

    response = http.HttpResponse(icalstream, content_type="text/calendar")
    response["Content-Type"] = "text/calendar; charset=utf-8"
    response["Filename"] = filename  # IE needs this
    response["Content-Disposition"] = "attachment; filename=%s" % filename
    response["X-Robots-Tag"] = "noindex, nofollow"

    # TODO(adamcik): add expires header that reduces load on old semesters

    return response
Ejemplo n.º 5
0
Archivo: views.py Proyecto: mydos/plan
def list_courses(request, year, semester_type, slug):
    '''Display a list of courses'''

    if request.method == 'POST':
        return select_course(request, year, semester_type, slug, add=True)

    courses = Course.objects.get_courses_with_exams(year, semester_type)
    return shortcuts.render(
        request, 'course_list.html', {
            'semester': Semester(year=year, type=semester_type),
            'course_list': courses,
        })
Ejemplo n.º 6
0
def select_groups(request, year, semester_type, slug):
    '''Form handler for selecting groups to use in schedule'''
    courses = Course.objects.get_courses(year, semester_type, slug)
    course_groups = Course.get_groups(year, semester_type, [c.id for c in courses])

    if request.method == 'POST':
        with transaction.atomic():
            for c in courses:
                try:
                    groups = course_groups[c.id]
                except KeyError: # Skip courses without groups
                    continue

                group_form = forms.GroupForm(groups, request.POST, prefix=c.id)

                if group_form.is_valid():
                    subscription = Subscription.objects.get_subscriptions(year,
                            semester_type, slug).get(course=c)

                    subscription.groups = group_form.cleaned_data['groups']

            return shortcuts.redirect(
                'schedule-advanced', year, Semester.localize(semester_type), slug)

    color_map = utils.ColorMap(hex=True)
    subscription_groups = Subscription.get_groups(year, semester_type, slug)
    all_subscripted_groups = set()

    for groups in subscription_groups.values():
        for group in groups:
            all_subscripted_groups.add(group)

    for c in courses:
        color_map[c.id]
        subscription_id = c.subscription_set.get(student__slug=slug).pk

        try:
            groups = course_groups[c.id]
        except KeyError: # Skip courses without groups
            continue

        initial_groups = subscription_groups.get(subscription_id, all_subscripted_groups)

        c.group_form = forms.GroupForm(groups, prefix=c.id, initial={'groups': initial_groups})

    return shortcuts.render(request, 'select_groups.html', {
            'semester': Semester(year=year, type=semester_type),
            'slug': slug,
            'courses': courses,
            'color_map': color_map,
        })
Ejemplo n.º 7
0
def schedule_current(request, year, semester_type, slug):
    semester = Semester(year=year, type=semester_type)
    current_week = get_current_week()

    weeks = Week.objects.filter(
        lecture__course__subscription__student__slug=slug,
        lecture__course__semester__year__exact=semester.year,
        lecture__course__semester__type=semester.type)
    weeks = weeks.distinct().values_list('number', flat=True)

    if current_week in weeks and semester.year == today().year:
        return shortcuts.redirect(
            'schedule-week', semester.year, semester.slug, slug, current_week)
    return shortcuts.redirect('schedule', semester.year, semester.slug, slug)
Ejemplo n.º 8
0
def select_lectures(request, year, semester_type, slug):
    '''Handle selection of lectures to hide'''

    if request.method == 'POST':
        excludes = request.POST.getlist('exclude')

        subscriptions = Subscription.objects.get_subscriptions(year, semester_type, slug)

        for subscription in subscriptions:
            if excludes:
                subscription.exclude = subscription.course.lecture_set.filter(id__in=excludes)
            else:
                subscription.exclude.clear()

    return shortcuts.redirect(
        'schedule-advanced', year, Semester.localize(semester_type), slug)
Ejemplo n.º 9
0
def select_lectures(request, year, semester_type, slug):
    """Handle selection of lectures to hide"""

    if request.method == "POST":
        with transaction.atomic():
            excludes = request.POST.getlist("exclude")

            subscriptions = Subscription.objects.get_subscriptions(year, semester_type, slug)

            for subscription in subscriptions:
                if excludes:
                    subscription.exclude = subscription.course.lecture_set.filter(id__in=excludes)
                else:
                    subscription.exclude.clear()

    return shortcuts.redirect("schedule-advanced", year, Semester.localize(semester_type), slug)
Ejemplo n.º 10
0
def select_lectures(request, year, semester_type, slug):
    '''Handle selection of lectures to hide'''

    if request.method == 'POST':
        with transaction.atomic():
            excludes = request.POST.getlist('exclude')

            subscriptions = Subscription.objects.get_subscriptions(year, semester_type, slug)

            for subscription in subscriptions:
                if excludes:
                    subscription.exclude = subscription.course.lecture_set.filter(id__in=excludes)
                else:
                    subscription.exclude.clear()

    return shortcuts.redirect(
        'schedule-advanced', year, Semester.localize(semester_type), slug)
Ejemplo n.º 11
0
def select_course(request, year, semester_type, slug, add=False):
    '''Handle selecting of courses from course list, change of names and
       removeall of courses'''

    # FIXME split ut three sub functions into seperate functions?

    try:
        semester = Semester.objects.get(year=year, type=semester_type)
    except Semester.DoesNotExist:
        return shortcuts.redirect(
            'schedule', year, Semester.localize(semester_type), slug)

    if request.method == 'POST':
        if 'submit_add' in request.POST or add:
            lookup = []

            for l in request.POST.getlist('course_add'):
                lookup.extend(l.replace(',', '').split())

            subscriptions = set(Subscription.objects.get_subscriptions(year,
                semester_type, slug).values_list('course__code', flat=True))

            errors = []
            to_many_subscriptions = False

            student, created = Student.objects.get_or_create(slug=slug)

            for l in lookup:
                try:
                    if len(subscriptions) > settings.TIMETABLE_MAX_COURSES:
                        to_many_subscriptions = True
                        break

                    course = Course.objects.get(
                            code__iexact=l.strip(),
                            semester__year__exact=year,
                            semester__type__exact=semester_type,
                        )

                    Subscription.objects.get_or_create(
                            student=student,
                            course=course,
                        )
                    subscriptions.add(course.code)

                except Course.DoesNotExist:
                    errors.append(l)

            if errors or to_many_subscriptions:
                return shortcuts.render(request, 'error.html', {
                        'courses': errors,
                        'max': settings.TIMETABLE_MAX_COURSES,
                        'slug': slug,
                        'year': year,
                        'type': semester_type,
                        'to_many_subscriptions': to_many_subscriptions,
                    })

            return shortcuts.redirect(
                'change-groups', year, Semester.localize(semester_type), slug)

        elif 'submit_remove' in request.POST:
            with transaction.atomic():
                courses = []
                for c in request.POST.getlist('course_remove'):
                    if c.strip():
                        courses.append(c.strip())

                Subscription.objects.get_subscriptions(year, semester_type, slug). \
                        filter(course__id__in=courses).delete()

                if Subscription.objects.filter(student__slug=slug).count() == 0:
                    Student.objects.filter(slug=slug).delete()

        elif 'submit_name' in request.POST:
            subscriptions = Subscription.objects.get_subscriptions(year, semester_type, slug)

            for u in subscriptions:
                form = forms.CourseAliasForm(request.POST, prefix=u.course_id)

                if form.is_valid():
                    alias = form.cleaned_data['alias'].strip()

                    if alias.upper() == u.course.code.upper() or alias == "":
                        # Leave as blank if we match the current course name
                        alias = ""

                    u.alias = alias
                    u.save()

    return shortcuts.redirect(
        'schedule-advanced', year, Semester.localize(semester_type), slug)
Ejemplo n.º 12
0
Archivo: views.py Proyecto: mydos/plan
def pdf(request, year, semester_type, slug, size=None, week=None):
    if size is not None and size not in ['A4', 'A5', 'A6', 'A7']:
        raise http.Http404

    semester = Semester(year=year, type=semester_type)

    color_map = ColorMap(hex=True)

    margin = 0.5*units.cm
    width, height = pagesizes.landscape(pagesizes.A5)

    width -= 2*margin
    height -= 2*margin

    time_width = 0.06 * width
    day_width = (width-time_width) / 5

    filename = '%s-%s-%s' % (year, semester.type, slug)

    if week:
        filename += '-%s' % week

    response = http.HttpResponse(mimetype='application/pdf')
    response['Content-Disposition'] = 'attachment; filename=%s.pdf' % filename

    lectures = Lecture.objects.get_lectures(year, semester.type, slug, week)
    rooms = Lecture.get_related(Room, lectures)
    courses = Course.objects.get_courses(year, semester.type, slug)

    for course in courses:
        color_map[course.id]

    timetable = Timetable(lectures)
    if lectures:
        timetable.place_lectures()
        timetable.do_expansion()
    timetable.insert_times()
    if week:
        timetable.set_week(semester.year, int(week))

    paragraph_style = default_styles['Normal']
    paragraph_style.fontName = 'Helvetica-Bold'
    paragraph_style.fontSize = 10
    paragraph_style.leading = 12

    table_style = _tablestyle()

    data = [[platypus.Paragraph(render_title(semester, slug, week), paragraph_style)]]
    data[-1].extend([''] * sum(timetable.span))
    table_style.add('SPAN', (0,0), (-1, 0))

    # Add days
    data.append([''])
    for span, date, name in timetable.header():
        if date:
            data[-1].append(dateformat.format(date, 'l - j M.'))
        else:
            data[-1].append(unicode(name))
        if span > 1:
            extra = span - 1
            table_style.add('SPAN', (len(data[-1])-1, 2), (len(data[-1])-1+extra, 2))
            data[-1].extend([''] * extra)

    # Convert to "simple" datastruct
    for row in timetable.table:
        data_row = []
        for cells in row:
            for cell in cells:
                time = cell.get('time', '')
                lecture = cell.get('lecture', '')

                if lecture:
                    if lecture.type and lecture.type.optional:
                        paragraph_style.fontName = 'Helvetica'

                    code = lecture.alias or lecture.course.code
                    content = [platypus.Paragraph(html.escape(code), paragraph_style)]
                    paragraph_style.leading = 8

                    if lecture.type:
                        content += [platypus.Paragraph(u'<font size=6>%s</font>' % lecture.type.name.replace('/', ' / '), paragraph_style)]

                    content += [platypus.Paragraph(u'<font size=6>%s</font>' % u', '.join(rooms.get(lecture.id, [])), paragraph_style)]

                    paragraph_style.leading = 12
                    paragraph_style.fontName = 'Helvetica-Bold'

                elif time:
                    content = time.replace(' - ', '\n')
                else:
                    content = ''

                if cell.get('remove', False):
                    data_row.append('')
                else:
                    data_row.append(content)

        data.append(data_row)

    # Calculate widths and line that splits days
    col_widths = [time_width]
    for w in timetable.span:
        x = len(col_widths)
        table_style.add('LINEBEFORE', (x, 2),  (x, -1),  1, outer_border)

        col_widths.extend([float(day_width)/w] * w)

    # Set row heights
    row_heights  = [16, 12]
    row_heights += [(height-(8*2)) / (len(data)-2)] * (len(data)-2)

    # Create spans, setup backgrounds and put content in KeepInFrame
    for lecture in timetable.lectures:
        offset = 0
        for o in timetable.span[:lecture['j']]:
            offset += o

        x1 = offset + lecture['k'] + 1
        y1 = lecture['i']+2

        x2 = x1 + lecture['width'] - 1
        y2 = y1 + lecture['height'] - 1

        table_style.add('SPAN', (x1, y1), (x2, y2))
        table_style.add('BACKGROUND', (x1, y1), (x2, y2),
                colors.HexColor(color_map[lecture['l'].course_id]))

        content = data[y1][x1]
        data[y1][x1] = platypus.KeepInFrame(col_widths[x1]*lecture['width'],
                                            row_heights[2]*lecture['height'],
                                            content, mode='shrink')

    page = canvas.Canvas(response, pagesizes.A4)
    page.translate(margin, pagesizes.A4[1]-margin)

    if 'A4' == size:
        page.translate(0.5*margin, 2.5*margin-pagesizes.A4[1])
        page.scale(1.414, 1.414)
        page.rotate(90)
    elif 'A6' == size:
        page.scale(0.707, 0.707)
    elif 'A7' == size:
        page.scale(0.5, 0.5)

    table = tables.Table(data, colWidths=col_widths, rowHeights=row_heights,
                         style=table_style)

    table.wrapOn(page, width, height)
    table.drawOn(page, 0, -height)

    note = request.META.get('HTTP_HOST', '').split(':')[0]

    page.setFont('Helvetica', 10)
    page.setFillColor(colors.HexColor('#666666'))
    page.drawString(width - page.stringWidth(note) - 2, -height+2, note)

    page.showPage()
    page.save()

    response['X-Robots-Tag'] = 'noindex, nofollow'
    return response
Ejemplo n.º 13
0
    def setUp(self):
        self.set_now_to(2009, 1, 1)

        self.semester = Semester(year=2009, type='spring')
        self.default_args = [self.semester.year, self.semester.type, 'adamcik']
Ejemplo n.º 14
0
def select_course(request, year, semester_type, slug, add=False):
    """Handle selecting of courses from course list, change of names and
       removeall of courses"""

    # FIXME split ut three sub functions into seperate functions?

    try:
        semester = Semester.objects.get(year=year, type=semester_type)
    except Semester.DoesNotExist:
        return shortcuts.redirect("schedule", year, Semester.localize(semester_type), slug)

    if request.method == "POST":
        if "submit_add" in request.POST or add:
            lookup = []

            for l in request.POST.getlist("course_add"):
                lookup.extend(l.replace(",", "").split())

            subscriptions = set(
                Subscription.objects.get_subscriptions(year, semester_type, slug).values_list("course__code", flat=True)
            )

            if not lookup:
                localized_semester = Semester.localize(semester_type)
                return shortcuts.redirect("schedule-advanced", year, localized_semester, slug)

            errors = []
            to_many_subscriptions = False

            student, created = Student.objects.get_or_create(slug=slug)

            for l in lookup:
                try:
                    if len(subscriptions) > settings.TIMETABLE_MAX_COURSES:
                        to_many_subscriptions = True
                        break

                    course = Course.objects.get(
                        code__iexact=l.strip(), semester__year__exact=year, semester__type__exact=semester_type
                    )

                    Subscription.objects.get_or_create(student=student, course=course)
                    subscriptions.add(course.code)

                except Course.DoesNotExist:
                    errors.append(l)

            if errors or to_many_subscriptions:
                return shortcuts.render(
                    request,
                    "error.html",
                    {
                        "courses": errors,
                        "max": settings.TIMETABLE_MAX_COURSES,
                        "slug": slug,
                        "year": year,
                        "type": semester_type,
                        "to_many_subscriptions": to_many_subscriptions,
                    },
                )

            return shortcuts.redirect("change-groups", year, Semester.localize(semester_type), slug)

        elif "submit_remove" in request.POST:
            with transaction.atomic():
                courses = []
                for c in request.POST.getlist("course_remove"):
                    if c.strip():
                        courses.append(c.strip())

                Subscription.objects.get_subscriptions(year, semester_type, slug).filter(
                    course__id__in=courses
                ).delete()

                if Subscription.objects.filter(student__slug=slug).count() == 0:
                    Student.objects.filter(slug=slug).delete()

        elif "submit_name" in request.POST:
            subscriptions = Subscription.objects.get_subscriptions(year, semester_type, slug)

            for u in subscriptions:
                form = forms.CourseAliasForm(request.POST, prefix=u.course_id)

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

                    if alias.upper() == u.course.code.upper() or alias == "":
                        # Leave as blank if we match the current course name
                        alias = ""

                    u.alias = alias
                    u.save()

    return shortcuts.redirect("schedule-advanced", year, Semester.localize(semester_type), slug)