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

Last change on this file since 8106 was 8106, checked in by Henrik Bettermann, 12 years ago

Move file widget templates to the browser package.

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