source: main/waeup.sirp/trunk/src/waeup/sirp/students/viewlets.py @ 7704

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

Remove unneeded import.

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