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

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

Callback requests in the base package are only for demonstration purposes. These components must be neutralized in the customization package.

  • Property svn:keywords set to Id
File size: 25.3 KB
Line 
1## $Id: viewlets.py 7997 2012-03-28 16:49:18Z 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,
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 = 'simulate_callback'
317
318    # This button must be neutralized
319    # in the customization package.
320    @property
321    def target_url(self):
322        if self.context.p_state == 'paid':
323            return ''
324        return self.view.url(self.view.context, self.target)
325
326class AddBedTicketActionButton(ManageActionButton):
327    grok.order(1)
328    grok.context(IStudentAccommodation)
329    grok.view(AccommodationManageFormPage)
330    grok.require('waeup.handleAccommodation')
331    icon = 'actionicon_home.png'
332    text = _('Book accommodation')
333    target = 'add'
334
335class BedTicketSlipActionButton(ManageActionButton):
336    grok.order(1)
337    grok.context(IBedTicket)
338    grok.view(BedTicketDisplayFormPage)
339    grok.require('waeup.handleAccommodation')
340    icon = 'actionicon_pdf.png'
341    text = _('Download bed allocation slip')
342    target = 'bed_allocation.pdf'
343
344class RelocateStudentActionButton(ManageActionButton):
345    grok.order(2)
346    grok.context(IBedTicket)
347    grok.view(BedTicketDisplayFormPage)
348    grok.require('waeup.manageHostels')
349    icon = 'actionicon_reload.png'
350    text = _('Relocate student')
351    target = 'relocate'
352
353class StudentBaseActionButton(ManageActionButton):
354    grok.order(1)
355    grok.context(IStudent)
356    grok.view(StudentBaseDisplayFormPage)
357    grok.require('waeup.handleStudent')
358    text = _('Edit')
359    target = 'edit_base'
360
361class StudentPasswordActionButton(ManageActionButton):
362    grok.order(2)
363    grok.context(IStudent)
364    grok.view(StudentBaseDisplayFormPage)
365    grok.require('waeup.handleStudent')
366    icon = 'actionicon_key.png'
367    text = _('Change password')
368    target = 'change_password'
369
370class StudentPassportActionButton(ManageActionButton):
371    grok.order(3)
372    grok.context(IStudent)
373    grok.view(StudentBaseDisplayFormPage)
374    grok.require('waeup.handleStudent')
375    icon = 'actionicon_portrait.png'
376    text = _('Change portrait')
377    target = 'change_portrait'
378
379    @property
380    def target_url(self):
381        if self.context.state != ADMITTED:
382            return ''
383        return self.view.url(self.view.context, self.target)
384
385class StudentClearanceStartActionButton(ManageActionButton):
386    grok.order(1)
387    grok.context(IStudent)
388    grok.view(StudentClearanceDisplayFormPage)
389    grok.require('waeup.handleStudent')
390    icon = 'actionicon_start.gif'
391    text = _('Start clearance')
392    target = 'start_clearance'
393
394    @property
395    def target_url(self):
396        if self.context.state != ADMITTED:
397            return ''
398        return self.view.url(self.view.context, self.target)
399
400class StudentClearanceEditActionButton(ManageActionButton):
401    grok.order(1)
402    grok.context(IStudent)
403    grok.view(StudentClearanceDisplayFormPage)
404    grok.require('waeup.handleStudent')
405    text = _('Edit')
406    target = 'cedit'
407
408    @property
409    def target_url(self):
410        if self.context.clearance_locked:
411            return ''
412        return self.view.url(self.view.context, self.target)
413
414class CourseRegistrationStartActionButton(ManageActionButton):
415    grok.order(1)
416    grok.context(IStudentStudyCourse)
417    grok.view(StudyCourseDisplayFormPage)
418    grok.require('waeup.handleStudent')
419    icon = 'actionicon_start.gif'
420    text = _('Start course registration')
421    target = 'start_course_registration'
422
423    @property
424    def target_url(self):
425        if not self.context.getStudent().state in (CLEARED,RETURNING):
426            return ''
427        return self.view.url(self.view.context, self.target)
428
429class AddStudyLevelActionButton(AddActionButton):
430    grok.order(1)
431    grok.context(IStudentStudyCourse)
432    grok.view(StudyCourseDisplayFormPage)
433    grok.require('waeup.handleStudent')
434    text = _('Add course list')
435    target = 'add'
436
437    @property
438    def target_url(self):
439        student = self.view.context.getStudent()
440        condition1 = student.state != PAID
441        condition2 = str(student['studycourse'].current_level) in \
442            self.view.context.keys()
443        if condition1 or condition2:
444            return ''
445        return self.view.url(self.view.context, self.target)
446
447class StudyLevelEditActionButton(ManageActionButton):
448    grok.order(1)
449    grok.context(IStudentStudyLevel)
450    grok.view(StudyLevelDisplayFormPage)
451    grok.require('waeup.handleStudent')
452    text = _('Add and remove courses')
453    target = 'edit'
454
455    @property
456    def target_url(self):
457        student = self.view.context.getStudent()
458        condition1 = student.state != PAID
459        condition2 = student[
460            'studycourse'].current_level != self.view.context.level
461        if condition1 or condition2:
462            return ''
463        return self.view.url(self.view.context, self.target)
464
465class StudentsTab(PrimaryNavTab):
466    """Students tab in primary navigation.
467    """
468
469    grok.context(IKofaObject)
470    grok.order(4)
471    grok.require('waeup.viewStudentsTab')
472
473    pnav = 4
474    tab_title = _(u'Students')
475
476    @property
477    def link_target(self):
478        return self.view.application_url('students')
479
480class PrimaryStudentNavManager(grok.ViewletManager):
481    """Viewlet manager for the primary navigation tab.
482    """
483    grok.name('primary_nav_student')
484
485class PrimaryStudentNavTab(grok.Viewlet):
486    """Base for primary student nav tabs.
487    """
488    grok.baseclass()
489    grok.viewletmanager(PrimaryStudentNavManager)
490    template = default_primary_nav_template
491    grok.order(1)
492    grok.require('waeup.Authenticated')
493    pnav = 0
494    tab_title = u'Some Text'
495
496    @property
497    def link_target(self):
498        return self.view.application_url()
499
500    @property
501    def active(self):
502        view_pnav = getattr(self.view, 'pnav', 0)
503        if view_pnav == self.pnav:
504            return 'active'
505        return ''
506
507class MyStudentDataTab(PrimaryStudentNavTab):
508    """MyData dropdown tab in primary navigation.
509    """
510    grok.order(3)
511    grok.require('waeup.viewMyStudentDataTab')
512    grok.template('mydatadropdowntabs')
513    pnav = 4
514    tab_title = _(u'My Data')
515
516    @property
517    def active(self):
518        view_pnav = getattr(self.view, 'pnav', 0)
519        if view_pnav == self.pnav:
520            return 'active dropdown'
521        return 'dropdown'
522
523    @property
524    def targets(self):
525        student_url = self.view.application_url() + (
526            '/students/%s' % self.request.principal.id)
527        #app_slip = getUtility(IExtFileStore).getFileByContext(
528        #    self.context.getStudent(), 'application_slip')
529        targets = []
530        #if app_slip:
531        #    targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
532        targets += [
533            {'url':student_url, 'title':'Base Data'},
534            {'url':student_url + '/view_clearance', 'title':_('Clearance Data')},
535            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
536            {'url':student_url + '/studycourse', 'title':_('Study Course')},
537            {'url':student_url + '/payments', 'title':_('Payments')},
538            {'url':student_url + '/accommodation', 'title':_('Accommodation Data')},
539            {'url':student_url + '/history', 'title':_('History')},
540            ]
541        return targets
542
543def handle_file_delete(context, view, download_name):
544    """Handle deletion of student file.
545
546    """
547    store = getUtility(IExtFileStore)
548    store.deleteFileByContext(context, attr=download_name)
549    write_log_message(view, 'deleted: %s' % download_name)
550    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
551    return
552
553def handle_file_upload(upload, context, view, max_size, download_name=None):
554    """Handle upload of student file.
555
556    Returns `True` in case of success or `False`.
557
558    Please note that file pointer passed in (`upload`) most probably
559    points to end of file when leaving this function.
560    """
561    # Check some file requirements first
562    if upload.filename.count('.') == 0:
563        view.flash(_('File name has no extension.'))
564        return False
565    if upload.filename.count('.') > 1:
566        view.flash(_('File name contains more than one dot.'))
567        return False
568    basename, expected_ext = os.path.splitext(download_name)
569    dummy, ext = os.path.splitext(upload.filename)
570    ext.lower()
571    if expected_ext:
572        if ext != expected_ext:
573            view.flash(_('${a} file extension expected.',
574                mapping = {'a':expected_ext.replace('.','')}))
575            return False
576    else:
577        if not ext.replace('.','') in ALLOWED_FILE_EXTENSIONS:
578            view.flash(
579                _('Only the following extension are allowed: ${a}',
580                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
581            return False
582        download_name += ext
583    size = file_size(upload)
584    if size > max_size:
585        view.flash(_('Uploaded file is too big.'))
586        return False
587    upload.seek(0) # file pointer moved when determining size
588    store = getUtility(IExtFileStore)
589    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
590    store.createFile(file_id, upload)
591    write_log_message(view, 'uploaded: %s (%s)' % (download_name,upload.filename))
592    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
593    return True
594
595class FileManager(grok.ViewletManager):
596    """Viewlet manager for uploading files, preferably scanned images.
597    """
598    grok.name('files')
599
600class FileDisplay(grok.Viewlet):
601    """Base file display viewlet.
602    """
603    grok.baseclass()
604    grok.context(IStudent)
605    grok.viewletmanager(FileManager)
606    grok.view(StudentClearanceDisplayFormPage)
607    grok.template('filedisplay')
608    grok.order(1)
609    grok.require('waeup.viewStudent')
610    label = _(u'File')
611    title = _(u'Scan')
612    download_name = u'filename.jpg'
613
614    @property
615    def file_exists(self):
616        image = getUtility(IExtFileStore).getFileByContext(
617            self.context, attr=self.download_name)
618        if image:
619            return True
620        else:
621            return False
622
623class FileUpload(FileDisplay):
624    """Base upload viewlet.
625    """
626    grok.baseclass()
627    grok.context(IStudent)
628    grok.viewletmanager(FileManager)
629    grok.view(StudentClearanceManageFormPage)
630    grok.template('fileupload')
631    grok.require('waeup.uploadStudentFile')
632    tab_redirect = '?tab2'
633    mus = 1024 * 150
634    upload_button =_('Upload new file')
635    delete_button = _('Delete attachment')
636
637    @property
638    def input_name(self):
639        return "%s" % self.__name__
640
641    def update(self):
642        self.max_upload_size = string_from_bytes(self.mus)
643        delete_button = self.request.form.get(
644            'delete_%s' % self.input_name, None)
645        upload_button = self.request.form.get(
646            'upload_%s' % self.input_name, None)
647        if delete_button:
648            handle_file_delete(
649                context=self.context, view=self.view,
650                download_name=self.download_name)
651            self.view.redirect(
652                self.view.url(
653                    self.context, self.view.__name__) + self.tab_redirect)
654            return
655        if upload_button:
656            upload = self.request.form.get(self.input_name, None)
657            if upload:
658                # We got a fresh upload
659                handle_file_upload(upload,
660                    self.context, self.view, self.mus, self.download_name)
661                self.view.redirect(
662                    self.view.url(
663                        self.context, self.view.__name__) + self.tab_redirect)
664            else:
665                self.view.flash(_('No local file selected.'))
666                self.view.redirect(
667                    self.view.url(
668                        self.context, self.view.__name__) + self.tab_redirect)
669        return
670
671class PassportDisplay(FileDisplay):
672    """Passport display viewlet.
673    """
674    grok.order(1)
675    grok.context(IStudent)
676    grok.view(StudentBaseDisplayFormPage)
677    grok.require('waeup.viewStudent')
678    grok.template('imagedisplay')
679    label = _(u'Passport Picture')
680    download_name = u'passport.jpg'
681
682class PassportUploadManage(FileUpload):
683    """Passport upload viewlet for officers.
684    """
685    grok.order(1)
686    grok.context(IStudent)
687    grok.view(StudentBaseManageFormPage)
688    grok.require('waeup.manageStudent')
689    grok.template('imageupload')
690    label = _(u'Passport Picture (jpg only)')
691    mus = 1024 * 50
692    download_name = u'passport.jpg'
693    tab_redirect = '?tab2'
694
695class PassportUploadEdit(PassportUploadManage):
696    """Passport upload viewlet for students.
697    """
698    grok.view(StudentFilesUploadPage)
699    grok.require('waeup.uploadStudentFile')
700
701class BirthCertificateDisplay(FileDisplay):
702    """Birth Certificate display viewlet.
703    """
704    grok.order(1)
705    label = _(u'Birth Certificate')
706    title = _(u'Birth Certificate Scan')
707    download_name = u'birth_certificate'
708
709class BirthCertificateSlip(BirthCertificateDisplay):
710    grok.view(ExportPDFClearanceSlipPage)
711
712class BirthCertificateUpload(FileUpload):
713    """Birth Certificate upload viewlet.
714    """
715    grok.order(1)
716    label = _(u'Birth Certificate')
717    title = _(u'Birth Certificate Scan')
718    mus = 1024 * 150
719    download_name = u'birth_certificate'
720    tab_redirect = '?tab2'
721
722class AcceptanceLetterDisplay(FileDisplay):
723    """Acceptance Letter display viewlet.
724    """
725    grok.order(1)
726    label = _(u'Acceptance Letter')
727    title = _(u'Acceptance Letter Scan')
728    download_name = u'acceptance_letter'
729
730class AcceptanceLetterSlip(AcceptanceLetterDisplay):
731    grok.view(ExportPDFClearanceSlipPage)
732
733class AcceptanceLetterUpload(FileUpload):
734    """AcceptanceLetter upload viewlet.
735    """
736    grok.order(2)
737    label = _(u'Acceptance Letter')
738    title = _(u'Acceptance Letter Scan')
739    mus = 1024 * 150
740    download_name = u'acceptance_letter'
741    tab_redirect = '?tab2'
742
743class Image(grok.View):
744    """Renders images for students.
745    """
746    grok.baseclass()
747    grok.name('none.jpg')
748    grok.context(IStudent)
749    grok.require('waeup.viewStudent')
750    download_name = u'none.jpg'
751
752    def render(self):
753        # A filename chooser turns a context into a filename suitable
754        # for file storage.
755        image = getUtility(IExtFileStore).getFileByContext(
756            self.context, attr=self.download_name)
757        if image is None:
758            # show placeholder image
759            self.response.setHeader('Content-Type', 'image/jpeg')
760            return open(DEFAULT_IMAGE_PATH, 'rb').read()
761        dummy,ext = os.path.splitext(image.name)
762        if ext == '.jpg':
763            self.response.setHeader('Content-Type', 'image/jpeg')
764        elif ext == '.png':
765            self.response.setHeader('Content-Type', 'image/png')
766        elif ext == '.pdf':
767            self.response.setHeader('Content-Type', 'application/pdf')
768        elif ext == '.tif':
769            self.response.setHeader('Content-Type', 'image/tiff')
770        return image
771
772class Passport(Image):
773    """Renders jpeg passport picture.
774    """
775    grok.name('passport.jpg')
776    download_name = u'passport.jpg'
777    grok.context(IStudent)
778
779class ApplicationSlipImage(Image):
780    """Renders application slip scan.
781    """
782    grok.name('application_slip')
783    download_name = u'application_slip'
784
785class BirthCertificateImage(Image):
786    """Renders birth certificate scan.
787    """
788    grok.name('birth_certificate')
789    download_name = u'birth_certificate'
790
791class AcceptanceLetterImage(Image):
792    """Renders acceptance letter scan.
793    """
794    grok.name('acceptance_letter')
795    download_name = u'acceptance_letter'
Note: See TracBrowser for help on using the repository browser.