source: main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py @ 7871

Last change on this file since 7871 was 7833, checked in by Henrik Bettermann, 13 years ago

In some cases we do no longer need to know the fallback language (= portal language) because the fallback language is already set in the cookie when accessing Kofa for the first time.

  • Property svn:keywords set to Id
File size: 25.3 KB
Line 
1## $Id: viewlets.py 7833 2012-03-10 09:45:25Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import os
19import grok
20from zope.component import getUtility
21from zope.interface import Interface
22from zope.i18n import translate
23from waeup.kofa.interfaces import (
24    IKofaObject, IExtFileStore, IFileStoreNameChooser, IKofaUtils)
25from waeup.kofa.interfaces import MessageFactory as _
26from waeup.kofa.utils.helpers import string_from_bytes, file_size
27from waeup.kofa.browser import DEFAULT_IMAGE_PATH
28from waeup.kofa.browser.viewlets import (
29    PrimaryNavTab, ManageActionButton, AddActionButton)
30from waeup.kofa.browser.layout import default_primary_nav_template
31from waeup.kofa.students.workflow import (ADMITTED, PAID,
32    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED)
33from waeup.kofa.students.browser import (
34    StudentClearanceManageFormPage,
35    write_log_message, StudentBaseManageFormPage,
36    StudentFilesUploadPage, ExportPDFClearanceSlipPage, StudentsContainerPage,
37    StudentsContainerManagePage, StudentBaseDisplayFormPage,
38    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
39    StudyCourseDisplayFormPage, StudyLevelDisplayFormPage,
40    CourseTicketDisplayFormPage, OnlinePaymentDisplayFormPage,
41    AccommodationManageFormPage, BedTicketDisplayFormPage,)
42from waeup.kofa.students.interfaces import (
43    IStudentsContainer, IStudent, IStudentClearance,
44    IStudentStudyCourse, IStudentAccommodation, IStudentStudyLevel,
45    ICourseTicket, IStudentOnlinePayment, IBedTicket,
46    )
47
48from waeup.kofa.interfaces import MessageFactory as _
49
50grok.context(IKofaObject) # Make IKofaObject the default context
51grok.templatedir('browser_templates')
52
53ALLOWED_FILE_EXTENSIONS = ('jpg', 'png', 'pdf', 'tif')
54
55class StudentManageSidebar(grok.ViewletManager):
56    grok.name('left_studentmanage')
57
58class StudentManageLink(grok.Viewlet):
59    """A link displayed in the student box which shows up for StudentNavigation
60    objects.
61
62    """
63    grok.baseclass()
64    grok.viewletmanager(StudentManageSidebar)
65    grok.context(IKofaObject)
66    grok.view(Interface)
67    grok.order(5)
68    grok.require('waeup.viewStudent')
69
70    link = 'index'
71    text = _(u'Base Data')
72
73    def render(self):
74        url = self.view.url(self.context.getStudent(), self.link)
75        # Here we know that the cookie has been set
76        lang = self.request.cookies.get('kofa.language')
77        text = translate(self.text, 'waeup.kofa',
78            target_language=lang)
79        return u'<li><a href="%s">%s</a></li>' % (
80                url, text)
81
82class StudentManageApplicationLink(StudentManageLink):
83    grok.order(1)
84    link = 'application_slip'
85    text = _(u'Application Slip')
86
87    def render(self):
88        slip = getUtility(IExtFileStore).getFileByContext(
89            self.context.getStudent(), attr=self.link)
90        if slip:
91            url = self.view.url(self.context,self.link)
92            return u'<li><a href="%s">%s</a></li>' % (
93                    url, self.text)
94        return ''
95
96class StudentManageBaseLink(StudentManageLink):
97    grok.order(2)
98    link = 'index'
99    text = _(u'Base Data')
100
101class StudentManageClearanceLink(StudentManageLink):
102    grok.order(3)
103    link = 'view_clearance'
104    text = _(u'Clearance Data')
105
106class StudentManagePersonalLink(StudentManageLink):
107    grok.order(4)
108    link = 'view_personal'
109    text = _(u'Personal Data')
110
111class StudentManageStudyCourseLink(StudentManageLink):
112    grok.order(5)
113    link = 'studycourse'
114    text = _(u'Study Course')
115
116class StudentManagePaymentsLink(StudentManageLink):
117    grok.order(6)
118    grok.require('waeup.payStudent')
119    link = 'payments'
120    text = _(u'Payments')
121
122class StudentManageAccommodationLink(StudentManageLink):
123    grok.order(7)
124    grok.require('waeup.handleAccommodation')
125    link = 'accommodation'
126    text = _(u'Accommodation')
127
128class StudentManageHistoryLink(StudentManageLink):
129    grok.order(8)
130    link = 'history'
131    text = _(u'History')
132
133
134class StudentsContainerManageActionButton(ManageActionButton):
135    grok.order(1)
136    grok.context(IStudentsContainer)
137    grok.view(StudentsContainerPage)
138    grok.require('waeup.manageStudent')
139    text = _('Manage student section')
140
141class StudentsContainerAddActionButton(AddActionButton):
142    grok.order(1)
143    grok.context(IStudentsContainer)
144    grok.view(StudentsContainerManagePage)
145    grok.require('waeup.manageStudent')
146    text = _('Add student')
147    target = 'addstudent'
148
149class ContactActionButton(ManageActionButton):
150    grok.order(4)
151    grok.context(IStudent)
152    grok.view(StudentBaseDisplayFormPage)
153    grok.require('waeup.manageStudent')
154    icon = 'actionicon_mail.png'
155    text = _('Send email')
156    target = 'contactstudent'
157
158class StudentBaseManageActionButton(ManageActionButton):
159    grok.order(1)
160    grok.context(IStudent)
161    grok.view(StudentBaseDisplayFormPage)
162    grok.require('waeup.manageStudent')
163    text = _('Manage')
164    target = 'manage_base'
165
166class StudentClearanceManageActionButton(ManageActionButton):
167    grok.order(1)
168    grok.context(IStudent)
169    grok.view(StudentClearanceDisplayFormPage)
170    grok.require('waeup.manageStudent')
171    text = _('Manage')
172    target = 'edit_clearance'
173
174class StudentClearActionButton(ManageActionButton):
175    grok.order(2)
176    grok.context(IStudent)
177    grok.view(StudentClearanceDisplayFormPage)
178    grok.require('waeup.clearStudent')
179    text = _('Clear student')
180    target = 'clear'
181    icon = 'actionicon_accept.png'
182
183    @property
184    def target_url(self):
185        if self.context.state != REQUESTED:
186            return ''
187        return self.view.url(self.view.context, self.target)
188
189class StudentRejectClearanceActionButton(ManageActionButton):
190    grok.order(3)
191    grok.context(IStudent)
192    grok.view(StudentClearanceDisplayFormPage)
193    grok.require('waeup.clearStudent')
194    text = _('Reject clearance')
195    target = 'reject_clearance'
196    icon = 'actionicon_reject.png'
197
198    @property
199    def target_url(self):
200        if self.context.state not in (REQUESTED, CLEARED):
201            return ''
202        return self.view.url(self.view.context, self.target)
203
204class ClearanceSlipActionButton(ManageActionButton):
205    grok.order(4)
206    grok.context(IStudent)
207    grok.view(StudentClearanceDisplayFormPage)
208    grok.require('waeup.viewStudent')
209    icon = 'actionicon_pdf.png'
210    text = _('Download clearance slip')
211    target = 'clearance.pdf'
212
213class StudentPersonalEditActionButton(ManageActionButton):
214    grok.order(1)
215    grok.context(IStudent)
216    grok.view(StudentPersonalDisplayFormPage)
217    grok.require('waeup.viewStudent')
218    text = _('Edit')
219    target = 'edit_personal'
220
221class StudyCourseManageActionButton(ManageActionButton):
222    grok.order(1)
223    grok.context(IStudentStudyCourse)
224    grok.view(StudyCourseDisplayFormPage)
225    grok.require('waeup.manageStudent')
226    text = _('Manage')
227    target = 'manage'
228
229class CourseRegistrationSlipActionButton(ManageActionButton):
230    grok.order(1)
231    grok.context(IStudentStudyLevel)
232    grok.view(StudyLevelDisplayFormPage)
233    grok.require('waeup.viewStudent')
234    icon = 'actionicon_pdf.png'
235    text = _('Download course registration slip')
236    target = 'course_registration.pdf'
237
238class StudyLevelManageActionButton(ManageActionButton):
239    grok.order(2)
240    grok.context(IStudentStudyLevel)
241    grok.view(StudyLevelDisplayFormPage)
242    grok.require('waeup.manageStudent')
243    text = _('Manage')
244    target = 'manage'
245
246class StudentValidateCoursesActionButton(ManageActionButton):
247    grok.order(3)
248    grok.context(IStudentStudyLevel)
249    grok.view(StudyLevelDisplayFormPage)
250    grok.require('waeup.validateStudent')
251    text = _('Validate courses')
252    target = 'validate_courses'
253    icon = 'actionicon_accept.png'
254
255    @property
256    def target_url(self):
257        if self.context.getStudent().state != REGISTERED or \
258            str(self.context.__parent__.current_level) != self.context.__name__:
259            return ''
260        return self.view.url(self.view.context, self.target)
261
262class StudentRejectCoursesActionButton(ManageActionButton):
263    grok.order(4)
264    grok.context(IStudentStudyLevel)
265    grok.view(StudyLevelDisplayFormPage)
266    grok.require('waeup.validateStudent')
267    text = _('Reject courses')
268    target = 'reject_courses'
269    icon = 'actionicon_reject.png'
270
271    @property
272    def target_url(self):
273        if self.context.getStudent().state not in (VALIDATED, REGISTERED) or \
274            str(self.context.__parent__.current_level) != self.context.__name__:
275            return ''
276        return self.view.url(self.view.context, self.target)
277
278class CourseTicketManageActionButton(ManageActionButton):
279    grok.order(1)
280    grok.context(ICourseTicket)
281    grok.view(CourseTicketDisplayFormPage)
282    grok.require('waeup.manageStudent')
283    text = _('Manage')
284    target = 'manage'
285
286#class OnlinePaymentManageActionButton(ManageActionButton):
287#    grok.order(1)
288#    grok.context(IStudentPaymentsContainer)
289#    grok.view(PaymentsDisplayFormPage)
290#    grok.require('waeup.manageStudent')
291#    text = 'Manage payments'
292#    target = 'manage'
293
294class PaymentReceiptActionButton(ManageActionButton):
295    grok.order(1)
296    grok.context(IStudentOnlinePayment)
297    grok.view(OnlinePaymentDisplayFormPage)
298    grok.require('waeup.viewStudent')
299    icon = 'actionicon_pdf.png'
300    text = _('Download payment receipt')
301    target = 'payment_receipt.pdf'
302
303    @property
304    def target_url(self):
305        if self.context.p_state != 'paid':
306            return ''
307        return self.view.url(self.view.context, self.target)
308
309class RequestCallbackActionButton(ManageActionButton):
310    grok.order(2)
311    grok.context(IStudentOnlinePayment)
312    grok.view(OnlinePaymentDisplayFormPage)
313    grok.require('waeup.payStudent')
314    icon = 'actionicon_call.png'
315    text = _('Request callback')
316    target = 'callback'
317
318    @property
319    def target_url(self):
320        if self.context.p_state != 'unpaid':
321            return ''
322        return self.view.url(self.view.context, self.target)
323
324class AddBedTicketActionButton(ManageActionButton):
325    grok.order(1)
326    grok.context(IStudentAccommodation)
327    grok.view(AccommodationManageFormPage)
328    grok.require('waeup.handleAccommodation')
329    icon = 'actionicon_home.png'
330    text = _('Book accommodation')
331    target = 'add'
332
333class BedTicketSlipActionButton(ManageActionButton):
334    grok.order(1)
335    grok.context(IBedTicket)
336    grok.view(BedTicketDisplayFormPage)
337    grok.require('waeup.handleAccommodation')
338    icon = 'actionicon_pdf.png'
339    text = _('Download bed allocation slip')
340    target = 'bed_allocation.pdf'
341
342class RelocateStudentActionButton(ManageActionButton):
343    grok.order(2)
344    grok.context(IBedTicket)
345    grok.view(BedTicketDisplayFormPage)
346    grok.require('waeup.manageHostels')
347    icon = 'actionicon_reload.png'
348    text = _('Relocate student')
349    target = 'relocate'
350
351class StudentBaseActionButton(ManageActionButton):
352    grok.order(1)
353    grok.context(IStudent)
354    grok.view(StudentBaseDisplayFormPage)
355    grok.require('waeup.handleStudent')
356    text = _('Edit base data')
357    target = 'edit_base'
358
359class StudentPasswordActionButton(ManageActionButton):
360    grok.order(2)
361    grok.context(IStudent)
362    grok.view(StudentBaseDisplayFormPage)
363    grok.require('waeup.handleStudent')
364    icon = 'actionicon_key.png'
365    text = _('Change password')
366    target = 'change_password'
367
368class StudentPassportActionButton(ManageActionButton):
369    grok.order(3)
370    grok.context(IStudent)
371    grok.view(StudentBaseDisplayFormPage)
372    grok.require('waeup.handleStudent')
373    icon = 'actionicon_portrait.png'
374    text = _('Change portrait')
375    target = 'change_portrait'
376
377    @property
378    def target_url(self):
379        if self.context.state != ADMITTED:
380            return ''
381        return self.view.url(self.view.context, self.target)
382
383class StudentClearanceStartActionButton(ManageActionButton):
384    grok.order(1)
385    grok.context(IStudent)
386    grok.view(StudentClearanceDisplayFormPage)
387    grok.require('waeup.handleStudent')
388    icon = 'actionicon_start.gif'
389    text = _('Start clearance')
390    target = 'start_clearance'
391
392    @property
393    def target_url(self):
394        if self.context.state != ADMITTED:
395            return ''
396        return self.view.url(self.view.context, self.target)
397
398class StudentClearanceEditActionButton(ManageActionButton):
399    grok.order(1)
400    grok.context(IStudent)
401    grok.view(StudentClearanceDisplayFormPage)
402    grok.require('waeup.handleStudent')
403    text = _('Edit')
404    target = 'cedit'
405
406    @property
407    def target_url(self):
408        if self.context.clearance_locked:
409            return ''
410        return self.view.url(self.view.context, self.target)
411
412class CourseRegistrationStartActionButton(ManageActionButton):
413    grok.order(1)
414    grok.context(IStudentStudyCourse)
415    grok.view(StudyCourseDisplayFormPage)
416    grok.require('waeup.handleStudent')
417    icon = 'actionicon_start.gif'
418    text = _('Start course registration')
419    target = 'start_course_registration'
420
421    @property
422    def target_url(self):
423        if not self.context.getStudent().state in (CLEARED,RETURNING):
424            return ''
425        return self.view.url(self.view.context, self.target)
426
427class AddStudyLevelActionButton(AddActionButton):
428    grok.order(1)
429    grok.context(IStudentStudyCourse)
430    grok.view(StudyCourseDisplayFormPage)
431    grok.require('waeup.handleStudent')
432    text = _('Add course list')
433    target = 'add'
434
435    @property
436    def target_url(self):
437        student = self.view.context.getStudent()
438        condition1 = student.state != PAID
439        condition2 = str(student['studycourse'].current_level) in \
440            self.view.context.keys()
441        if condition1 or condition2:
442            return ''
443        return self.view.url(self.view.context, self.target)
444
445class StudyLevelEditActionButton(ManageActionButton):
446    grok.order(1)
447    grok.context(IStudentStudyLevel)
448    grok.view(StudyLevelDisplayFormPage)
449    grok.require('waeup.handleStudent')
450    text = _('Add and remove courses')
451    target = 'edit'
452
453    @property
454    def target_url(self):
455        student = self.view.context.getStudent()
456        condition1 = student.state != PAID
457        condition2 = student[
458            'studycourse'].current_level != self.view.context.level
459        if condition1 or condition2:
460            return ''
461        return self.view.url(self.view.context, self.target)
462
463class StudentsTab(PrimaryNavTab):
464    """Students tab in primary navigation.
465    """
466
467    grok.context(IKofaObject)
468    grok.order(4)
469    grok.require('waeup.viewStudentsTab')
470
471    pnav = 4
472    tab_title = _(u'Students')
473
474    @property
475    def link_target(self):
476        return self.view.application_url('students')
477
478class PrimaryStudentNavManager(grok.ViewletManager):
479    """Viewlet manager for the primary navigation tab.
480    """
481    grok.name('primary_nav_student')
482
483class PrimaryStudentNavTab(grok.Viewlet):
484    """Base for primary student nav tabs.
485    """
486    grok.baseclass()
487    grok.viewletmanager(PrimaryStudentNavManager)
488    template = default_primary_nav_template
489    grok.order(1)
490    grok.require('waeup.Authenticated')
491    pnav = 0
492    tab_title = u'Some Text'
493
494    @property
495    def link_target(self):
496        return self.view.application_url()
497
498    @property
499    def active(self):
500        view_pnav = getattr(self.view, 'pnav', 0)
501        if view_pnav == self.pnav:
502            return 'active'
503        return ''
504
505class MyStudentDataTab(PrimaryStudentNavTab):
506    """MyData dropdown tab in primary navigation.
507    """
508    grok.order(3)
509    grok.require('waeup.viewMyStudentDataTab')
510    grok.template('mydatadropdowntabs')
511    pnav = 4
512    tab_title = _(u'My Data')
513
514    @property
515    def active(self):
516        view_pnav = getattr(self.view, 'pnav', 0)
517        if view_pnav == self.pnav:
518            return 'active dropdown'
519        return 'dropdown'
520
521    @property
522    def targets(self):
523        student_url = self.view.application_url() + (
524            '/students/%s' % self.request.principal.id)
525        #app_slip = getUtility(IExtFileStore).getFileByContext(
526        #    self.context.getStudent(), 'application_slip')
527        targets = []
528        #if app_slip:
529        #    targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
530        targets += [
531            {'url':student_url, 'title':'Base Data'},
532            {'url':student_url + '/view_clearance', 'title':_('Clearance Data')},
533            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
534            {'url':student_url + '/studycourse', 'title':_('Study Course')},
535            {'url':student_url + '/payments', 'title':_('Payments')},
536            {'url':student_url + '/accommodation', 'title':_('Accommodation Data')},
537            {'url':student_url + '/history', 'title':_('History')},
538            ]
539        return targets
540
541def handle_file_delete(context, view, download_name):
542    """Handle deletion of student file.
543
544    """
545    store = getUtility(IExtFileStore)
546    store.deleteFileByContext(context, attr=download_name)
547    write_log_message(view, 'deleted: %s' % download_name)
548    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
549    return
550
551def handle_file_upload(upload, context, view, max_size, download_name=None):
552    """Handle upload of student file.
553
554    Returns `True` in case of success or `False`.
555
556    Please note that file pointer passed in (`upload`) most probably
557    points to end of file when leaving this function.
558    """
559    # Check some file requirements first
560    if upload.filename.count('.') == 0:
561        view.flash(_('File name has no extension.'))
562        return False
563    if upload.filename.count('.') > 1:
564        view.flash(_('File name contains more than one dot.'))
565        return False
566    basename, expected_ext = os.path.splitext(download_name)
567    dummy, ext = os.path.splitext(upload.filename)
568    ext.lower()
569    if expected_ext:
570        if ext != expected_ext:
571            view.flash(_('${a} file extension expected.',
572                mapping = {'a':expected_ext.replace('.','')}))
573            return False
574    else:
575        if not ext.replace('.','') in ALLOWED_FILE_EXTENSIONS:
576            view.flash(
577                _('Only the following extension are allowed: ${a}',
578                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
579            return False
580        download_name += ext
581    size = file_size(upload)
582    if size > max_size:
583        view.flash(_('Uploaded file is too big.'))
584        return False
585    upload.seek(0) # file pointer moved when determining size
586    store = getUtility(IExtFileStore)
587    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
588    store.createFile(file_id, upload)
589    write_log_message(view, 'uploaded: %s (%s)' % (download_name,upload.filename))
590    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
591    return True
592
593class FileManager(grok.ViewletManager):
594    """Viewlet manager for uploading files, preferably scanned images.
595    """
596    grok.name('files')
597
598class FileDisplay(grok.Viewlet):
599    """Base file display viewlet.
600    """
601    grok.baseclass()
602    grok.context(IStudentClearance)
603    grok.viewletmanager(FileManager)
604    grok.view(StudentClearanceDisplayFormPage)
605    grok.template('filedisplay')
606    grok.order(1)
607    grok.require('waeup.viewStudent')
608    label = _(u'File')
609    title = _(u'Scan')
610    download_name = u'filename.jpg'
611
612    @property
613    def file_exists(self):
614        image = getUtility(IExtFileStore).getFileByContext(
615            self.context, attr=self.download_name)
616        if image:
617            return True
618        else:
619            return False
620
621class FileUpload(FileDisplay):
622    """Base upload viewlet.
623    """
624    grok.baseclass()
625    grok.context(IStudentClearance)
626    grok.viewletmanager(FileManager)
627    grok.view(StudentClearanceManageFormPage)
628    grok.template('fileupload')
629    grok.require('waeup.uploadStudentFile')
630    tab_redirect = '?tab2'
631    mus = 1024 * 150
632    upload_button =_('Upload new file')
633    delete_button = _('Delete attachment')
634
635    @property
636    def input_name(self):
637        return "%s" % self.__name__
638
639    def update(self):
640        self.max_upload_size = string_from_bytes(self.mus)
641        delete_button = self.request.form.get(
642            'delete_%s' % self.input_name, None)
643        upload_button = self.request.form.get(
644            'upload_%s' % self.input_name, None)
645        if delete_button:
646            handle_file_delete(
647                context=self.context, view=self.view,
648                download_name=self.download_name)
649            self.view.redirect(
650                self.view.url(
651                    self.context, self.view.__name__) + self.tab_redirect)
652            return
653        if upload_button:
654            upload = self.request.form.get(self.input_name, None)
655            if upload:
656                # We got a fresh upload
657                handle_file_upload(upload,
658                    self.context, self.view, self.mus, self.download_name)
659                self.view.redirect(
660                    self.view.url(
661                        self.context, self.view.__name__) + self.tab_redirect)
662            else:
663                self.view.flash(_('No local file selected.'))
664                self.view.redirect(
665                    self.view.url(
666                        self.context, self.view.__name__) + self.tab_redirect)
667        return
668
669class PassportDisplay(FileDisplay):
670    """Passport display viewlet.
671    """
672    grok.order(1)
673    grok.context(IStudent)
674    grok.view(StudentBaseDisplayFormPage)
675    grok.require('waeup.viewStudent')
676    grok.template('imagedisplay')
677    label = _(u'Passport Picture')
678    download_name = u'passport.jpg'
679
680class PassportUploadManage(FileUpload):
681    """Passport upload viewlet for officers.
682    """
683    grok.order(1)
684    grok.context(IStudent)
685    grok.view(StudentBaseManageFormPage)
686    grok.require('waeup.manageStudent')
687    grok.template('imageupload')
688    label = _(u'Passport Picture (jpg only)')
689    mus = 1024 * 50
690    download_name = u'passport.jpg'
691    tab_redirect = '?tab2'
692
693class PassportUploadEdit(PassportUploadManage):
694    """Passport upload viewlet for students.
695    """
696    grok.view(StudentFilesUploadPage)
697    grok.require('waeup.uploadStudentFile')
698
699class BirthCertificateDisplay(FileDisplay):
700    """Birth Certificate display viewlet.
701    """
702    grok.order(1)
703    label = _(u'Birth Certificate')
704    title = _(u'Birth Certificate Scan')
705    download_name = u'birth_certificate'
706
707class BirthCertificateSlip(BirthCertificateDisplay):
708    grok.view(ExportPDFClearanceSlipPage)
709
710class BirthCertificateUpload(FileUpload):
711    """Birth Certificate upload viewlet.
712    """
713    grok.order(1)
714    label = _(u'Birth Certificate')
715    title = _(u'Birth Certificate Scan')
716    mus = 1024 * 150
717    download_name = u'birth_certificate'
718    tab_redirect = '?tab2'
719
720class AcceptanceLetterDisplay(FileDisplay):
721    """Acceptance Letter display viewlet.
722    """
723    grok.order(1)
724    label = _(u'Acceptance Letter')
725    title = _(u'Acceptance Letter Scan')
726    download_name = u'acceptance_letter'
727
728class AcceptanceLetterSlip(AcceptanceLetterDisplay):
729    grok.view(ExportPDFClearanceSlipPage)
730
731class AcceptanceLetterUpload(FileUpload):
732    """AcceptanceLetter upload viewlet.
733    """
734    grok.order(2)
735    label = _(u'Acceptance Letter')
736    title = _(u'Acceptance Letter Scan')
737    mus = 1024 * 150
738    download_name = u'acceptance_letter'
739    tab_redirect = '?tab2'
740
741class Image(grok.View):
742    """Renders images for students.
743    """
744    grok.baseclass()
745    grok.name('none.jpg')
746    grok.context(IStudentClearance)
747    grok.require('waeup.viewStudent')
748    download_name = u'none.jpg'
749
750    def render(self):
751        # A filename chooser turns a context into a filename suitable
752        # for file storage.
753        image = getUtility(IExtFileStore).getFileByContext(
754            self.context, attr=self.download_name)
755        if image is None:
756            # show placeholder image
757            self.response.setHeader('Content-Type', 'image/jpeg')
758            return open(DEFAULT_IMAGE_PATH, 'rb').read()
759        dummy,ext = os.path.splitext(image.name)
760        if ext == '.jpg':
761            self.response.setHeader('Content-Type', 'image/jpeg')
762        elif ext == '.png':
763            self.response.setHeader('Content-Type', 'image/png')
764        elif ext == '.pdf':
765            self.response.setHeader('Content-Type', 'application/pdf')
766        elif ext == '.tif':
767            self.response.setHeader('Content-Type', 'image/tiff')
768        return image
769
770class Passport(Image):
771    """Renders jpeg passport picture.
772    """
773    grok.name('passport.jpg')
774    download_name = u'passport.jpg'
775    grok.context(IStudent)
776
777class ApplicationSlipImage(Image):
778    """Renders application slip scan.
779    """
780    grok.name('application_slip')
781    download_name = u'application_slip'
782
783class BirthCertificateImage(Image):
784    """Renders birth certificate scan.
785    """
786    grok.name('birth_certificate')
787    download_name = u'birth_certificate'
788
789class AcceptanceLetterImage(Image):
790    """Renders acceptance letter scan.
791    """
792    grok.name('acceptance_letter')
793    download_name = u'acceptance_letter'
Note: See TracBrowser for help on using the repository browser.