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

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

Import message factory from interfaces

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