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

Last change on this file since 8467 was 8467, checked in by uli, 12 years ago

Use fileformat recognition when uploading student files.

  • Property svn:keywords set to Id
File size: 25.8 KB
Line 
1## $Id: viewlets.py 8467 2012-05-18 00:13:37Z uli $
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)
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, default_filedisplay_template,
32    default_fileupload_template)
33from waeup.kofa.students.workflow import (
34    ADMITTED, PAID, REQUESTED, RETURNING, CLEARED, REGISTERED,
35    VALIDATED)
36from waeup.kofa.students.browser import (
37    StudentClearanceManageFormPage, write_log_message,
38    StudentBaseManageFormPage, StudentFilesUploadPage,
39    ExportPDFClearanceSlipPage, StudentsContainerPage,
40    StudentsContainerManagePage, StudentBaseDisplayFormPage,
41    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
42    StudyCourseDisplayFormPage, StudyLevelDisplayFormPage,
43    CourseTicketDisplayFormPage, OnlinePaymentDisplayFormPage,
44    AccommodationManageFormPage, BedTicketDisplayFormPage,
45    StudentClearanceEditFormPage, StudentPersonalEditFormPage)
46from waeup.kofa.students.interfaces import (
47    IStudentsContainer, IStudent, IStudentStudyCourse, IStudentAccommodation,
48    IStudentStudyLevel, ICourseTicket, IStudentOnlinePayment, IBedTicket,
49    )
50from waeup.kofa.utils.helpers import get_fileformat
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 = 'manage_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 ClearanceViewActionButton(ManageActionButton):
216    grok.order(1)
217    grok.context(IStudent)
218    grok.view(StudentClearanceEditFormPage)
219    grok.require('waeup.viewStudent')
220    icon = 'actionicon_view.png'
221    text = _('View')
222    target = 'view_clearance'
223
224class PersonalViewActionButton(ManageActionButton):
225    grok.order(1)
226    grok.context(IStudent)
227    grok.view(StudentPersonalEditFormPage)
228    grok.require('waeup.viewStudent')
229    icon = 'actionicon_view.png'
230    text = _('View')
231    target = 'view_personal'
232
233class StudentPersonalEditActionButton(ManageActionButton):
234    grok.order(1)
235    grok.context(IStudent)
236    grok.view(StudentPersonalDisplayFormPage)
237    grok.require('waeup.viewStudent')
238    text = _('Edit')
239    target = 'edit_personal'
240
241class StudyCourseManageActionButton(ManageActionButton):
242    grok.order(1)
243    grok.context(IStudentStudyCourse)
244    grok.view(StudyCourseDisplayFormPage)
245    grok.require('waeup.manageStudent')
246    text = _('Manage')
247    target = 'manage'
248
249class StudyLevelManageActionButton(ManageActionButton):
250    grok.order(1)
251    grok.context(IStudentStudyLevel)
252    grok.view(StudyLevelDisplayFormPage)
253    grok.require('waeup.manageStudent')
254    text = _('Manage')
255    target = 'manage'
256
257class StudentValidateCoursesActionButton(ManageActionButton):
258    grok.order(3)
259    grok.context(IStudentStudyLevel)
260    grok.view(StudyLevelDisplayFormPage)
261    grok.require('waeup.validateStudent')
262    text = _('Validate courses')
263    target = 'validate_courses'
264    icon = 'actionicon_accept.png'
265
266    @property
267    def target_url(self):
268        if self.context.getStudent().state != 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 StudentRejectCoursesActionButton(ManageActionButton):
274    grok.order(4)
275    grok.context(IStudentStudyLevel)
276    grok.view(StudyLevelDisplayFormPage)
277    grok.require('waeup.validateStudent')
278    text = _('Reject courses')
279    target = 'reject_courses'
280    icon = 'actionicon_reject.png'
281
282    @property
283    def target_url(self):
284        if self.context.getStudent().state not in (VALIDATED, REGISTERED) or \
285            str(self.context.__parent__.current_level) != self.context.__name__:
286            return ''
287        return self.view.url(self.view.context, self.target)
288
289class CourseRegistrationSlipActionButton(ManageActionButton):
290    grok.order(5)
291    grok.context(IStudentStudyLevel)
292    grok.view(StudyLevelDisplayFormPage)
293    grok.require('waeup.viewStudent')
294    icon = 'actionicon_pdf.png'
295    text = _('Download course registration slip')
296    target = 'course_registration.pdf'
297
298class CourseTicketManageActionButton(ManageActionButton):
299    grok.order(1)
300    grok.context(ICourseTicket)
301    grok.view(CourseTicketDisplayFormPage)
302    grok.require('waeup.manageStudent')
303    text = _('Manage')
304    target = 'manage'
305
306#class OnlinePaymentManageActionButton(ManageActionButton):
307#    grok.order(1)
308#    grok.context(IStudentPaymentsContainer)
309#    grok.view(PaymentsDisplayFormPage)
310#    grok.require('waeup.manageStudent')
311#    text = 'Manage payments'
312#    target = 'manage'
313
314class PaymentReceiptActionButton(ManageActionButton):
315    grok.order(1)
316    grok.context(IStudentOnlinePayment)
317    grok.view(OnlinePaymentDisplayFormPage)
318    grok.require('waeup.viewStudent')
319    icon = 'actionicon_pdf.png'
320    text = _('Download payment slip')
321    target = 'payment_slip.pdf'
322
323    @property
324    def target_url(self):
325        #if self.context.p_state != 'paid':
326        #    return ''
327        return self.view.url(self.view.context, self.target)
328
329
330class ApprovePaymentActionButton(ManageActionButton):
331    grok.order(2)
332    grok.context(IStudentOnlinePayment)
333    grok.view(OnlinePaymentDisplayFormPage)
334    grok.require('waeup.managePortal')
335    icon = 'actionicon_accept.png'
336    text = _('Approve payment')
337    target = 'approve'
338
339    @property
340    def target_url(self):
341        if self.context.p_state == 'paid':
342            return ''
343        return self.view.url(self.view.context, self.target)
344
345class AddBedTicketActionButton(ManageActionButton):
346    grok.order(1)
347    grok.context(IStudentAccommodation)
348    grok.view(AccommodationManageFormPage)
349    grok.require('waeup.handleAccommodation')
350    icon = 'actionicon_home.png'
351    text = _('Book accommodation')
352    target = 'add'
353
354class BedTicketSlipActionButton(ManageActionButton):
355    grok.order(1)
356    grok.context(IBedTicket)
357    grok.view(BedTicketDisplayFormPage)
358    grok.require('waeup.handleAccommodation')
359    icon = 'actionicon_pdf.png'
360    text = _('Download bed allocation slip')
361    target = 'bed_allocation.pdf'
362
363class RelocateStudentActionButton(ManageActionButton):
364    grok.order(2)
365    grok.context(IBedTicket)
366    grok.view(BedTicketDisplayFormPage)
367    grok.require('waeup.manageHostels')
368    icon = 'actionicon_reload.png'
369    text = _('Relocate student')
370    target = 'relocate'
371
372class StudentBaseActionButton(ManageActionButton):
373    grok.order(1)
374    grok.context(IStudent)
375    grok.view(StudentBaseDisplayFormPage)
376    grok.require('waeup.handleStudent')
377    text = _('Edit')
378    target = 'edit_base'
379
380class StudentPasswordActionButton(ManageActionButton):
381    grok.order(2)
382    grok.context(IStudent)
383    grok.view(StudentBaseDisplayFormPage)
384    grok.require('waeup.handleStudent')
385    icon = 'actionicon_key.png'
386    text = _('Change password')
387    target = 'change_password'
388
389class StudentPassportActionButton(ManageActionButton):
390    grok.order(3)
391    grok.context(IStudent)
392    grok.view(StudentBaseDisplayFormPage)
393    grok.require('waeup.handleStudent')
394    icon = 'actionicon_portrait.png'
395    text = _('Change portrait')
396    target = 'change_portrait'
397
398    @property
399    def target_url(self):
400        if self.context.state != ADMITTED:
401            return ''
402        return self.view.url(self.view.context, self.target)
403
404class StudentClearanceStartActionButton(ManageActionButton):
405    grok.order(1)
406    grok.context(IStudent)
407    grok.view(StudentClearanceDisplayFormPage)
408    grok.require('waeup.handleStudent')
409    icon = 'actionicon_start.gif'
410    text = _('Start clearance')
411    target = 'start_clearance'
412
413    @property
414    def target_url(self):
415        if self.context.state != ADMITTED:
416            return ''
417        return self.view.url(self.view.context, self.target)
418
419class StudentClearanceEditActionButton(ManageActionButton):
420    grok.order(1)
421    grok.context(IStudent)
422    grok.view(StudentClearanceDisplayFormPage)
423    grok.require('waeup.handleStudent')
424    text = _('Edit')
425    target = 'cedit'
426
427    @property
428    def target_url(self):
429        if self.context.clearance_locked:
430            return ''
431        return self.view.url(self.view.context, self.target)
432
433class CourseRegistrationStartActionButton(ManageActionButton):
434    grok.order(1)
435    grok.context(IStudentStudyCourse)
436    grok.view(StudyCourseDisplayFormPage)
437    grok.require('waeup.handleStudent')
438    icon = 'actionicon_start.gif'
439    text = _('Start course registration')
440    target = 'start_course_registration'
441
442    @property
443    def target_url(self):
444        if not self.context.getStudent().state in (CLEARED,RETURNING) \
445            or not self.context.may_register:
446            return ''
447        return self.view.url(self.view.context, self.target)
448
449class AddStudyLevelActionButton(AddActionButton):
450    grok.order(1)
451    grok.context(IStudentStudyCourse)
452    grok.view(StudyCourseDisplayFormPage)
453    grok.require('waeup.handleStudent')
454    text = _('Add course list')
455    target = 'add'
456
457    @property
458    def target_url(self):
459        student = self.view.context.getStudent()
460        condition1 = student.state != PAID
461        condition2 = str(student['studycourse'].current_level) in \
462            self.view.context.keys()
463        if condition1 or condition2:
464            return ''
465        return self.view.url(self.view.context, self.target)
466
467class StudyLevelEditActionButton(ManageActionButton):
468    grok.order(2)
469    grok.context(IStudentStudyLevel)
470    grok.view(StudyLevelDisplayFormPage)
471    grok.require('waeup.handleStudent')
472    text = _('Add and remove courses')
473    target = 'edit'
474
475    @property
476    def target_url(self):
477        student = self.view.context.getStudent()
478        condition1 = student.state != PAID
479        condition2 = student[
480            'studycourse'].current_level != self.view.context.level
481        if condition1 or condition2:
482            return ''
483        return self.view.url(self.view.context, self.target)
484
485class StudentsTab(PrimaryNavTab):
486    """Students tab in primary navigation.
487    """
488
489    grok.context(IKofaObject)
490    grok.order(4)
491    grok.require('waeup.viewStudentsTab')
492
493    pnav = 4
494    tab_title = _(u'Students')
495
496    @property
497    def link_target(self):
498        return self.view.application_url('students')
499
500class PrimaryStudentNavManager(grok.ViewletManager):
501    """Viewlet manager for the primary navigation tab.
502    """
503    grok.name('primary_nav_student')
504
505class PrimaryStudentNavTab(grok.Viewlet):
506    """Base for primary student nav tabs.
507    """
508    grok.baseclass()
509    grok.viewletmanager(PrimaryStudentNavManager)
510    template = default_primary_nav_template
511    grok.order(1)
512    grok.require('waeup.Authenticated')
513    pnav = 0
514    tab_title = u'Some Text'
515
516    @property
517    def link_target(self):
518        return self.view.application_url()
519
520    @property
521    def active(self):
522        view_pnav = getattr(self.view, 'pnav', 0)
523        if view_pnav == self.pnav:
524            return 'active'
525        return ''
526
527class MyStudentDataTab(PrimaryStudentNavTab):
528    """MyData dropdown tab in primary navigation.
529    """
530    grok.order(3)
531    grok.require('waeup.viewMyStudentDataTab')
532    grok.template('mydatadropdowntabs')
533    pnav = 4
534    tab_title = _(u'My Data')
535
536    @property
537    def active(self):
538        view_pnav = getattr(self.view, 'pnav', 0)
539        if view_pnav == self.pnav:
540            return 'active dropdown'
541        return 'dropdown'
542
543    @property
544    def targets(self):
545        student_url = self.view.application_url() + (
546            '/students/%s' % self.request.principal.id)
547        #app_slip = getUtility(IExtFileStore).getFileByContext(
548        #    self.context.getStudent(), 'application_slip')
549        targets = []
550        #if app_slip:
551        #    targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
552        targets += [
553            {'url':student_url, 'title':'Base Data'},
554            {'url':student_url + '/view_clearance',
555             'title':_('Clearance Data')},
556            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
557            {'url':student_url + '/studycourse', 'title':_('Study Course')},
558            {'url':student_url + '/payments', 'title':_('Payments')},
559            {'url':student_url + '/accommodation',
560             'title':_('Accommodation Data')},
561            {'url':student_url + '/history', 'title':_('History')},
562            ]
563        return targets
564
565def handle_file_delete(context, view, download_name):
566    """Handle deletion of student file.
567
568    """
569    store = getUtility(IExtFileStore)
570    store.deleteFileByContext(context, attr=download_name)
571    write_log_message(view, 'deleted: %s' % download_name)
572    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
573    return
574
575def handle_file_upload(upload, context, view, max_size, download_name=None):
576    """Handle upload of student file.
577
578    Returns `True` in case of success or `False`.
579
580    Please note that file pointer passed in (`upload`) most probably
581    points to end of file when leaving this function.
582    """
583    # Check some file requirements first
584    size = file_size(upload)
585    if size > max_size:
586        view.flash(_('Uploaded file is too big.'))
587        return False
588    upload.seek(0) # file pointer moved when determining size
589    file_format = get_fileformat(None, upload.read(512))
590    upload.seek(0) # same here
591    if file_format is None:
592        view.flash(_('Could not determine file type.'))
593        return False
594    basename, expected_ext = os.path.splitext(download_name)
595    if expected_ext:
596        if '.' + file_format != expected_ext:
597            view.flash(_('${a} file extension expected.',
598                mapping = {'a':expected_ext[1:]}))
599            return False
600    else:
601        if not file_format in ALLOWED_FILE_EXTENSIONS:
602            view.flash(
603                _('Only the following extensions are allowed: ${a}',
604                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
605            return False
606        download_name += '.' + file_format
607    store = getUtility(IExtFileStore)
608    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
609    store.createFile(file_id, upload)
610    write_log_message(view, 'uploaded: %s (%s)' % (
611        download_name,upload.filename))
612    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
613    return True
614
615class FileManager(grok.ViewletManager):
616    """Viewlet manager for uploading files, preferably scanned images.
617    """
618    grok.name('files')
619
620class FileDisplay(grok.Viewlet):
621    """Base file display viewlet.
622    """
623    grok.baseclass()
624    grok.context(IStudent)
625    grok.viewletmanager(FileManager)
626    grok.view(StudentClearanceDisplayFormPage)
627    template = default_filedisplay_template
628    grok.order(1)
629    grok.require('waeup.viewStudent')
630    label = _(u'File')
631    title = _(u'Scan')
632    download_name = u'filename.jpg'
633
634    @property
635    def file_exists(self):
636        image = getUtility(IExtFileStore).getFileByContext(
637            self.context, attr=self.download_name)
638        if image:
639            return True
640        else:
641            return False
642
643class FileUpload(FileDisplay):
644    """Base upload viewlet.
645    """
646    grok.baseclass()
647    grok.context(IStudent)
648    grok.viewletmanager(FileManager)
649    grok.view(StudentClearanceManageFormPage)
650    template = default_fileupload_template
651    grok.require('waeup.uploadStudentFile')
652    tab_redirect = '?tab2'
653    mus = 1024 * 150
654    upload_button =_('Upload new file')
655    delete_button = _('Delete attachment')
656    show_viewlet = True
657
658    @property
659    def input_name(self):
660        return "%s" % self.__name__
661
662    def update(self):
663        self.max_upload_size = string_from_bytes(self.mus)
664        delete_button = self.request.form.get(
665            'delete_%s' % self.input_name, None)
666        upload_button = self.request.form.get(
667            'upload_%s' % self.input_name, None)
668        if delete_button:
669            handle_file_delete(
670                context=self.context, view=self.view,
671                download_name=self.download_name)
672            self.view.redirect(
673                self.view.url(
674                    self.context, self.view.__name__) + self.tab_redirect)
675            return
676        if upload_button:
677            upload = self.request.form.get(self.input_name, None)
678            if upload:
679                # We got a fresh upload
680                handle_file_upload(upload,
681                    self.context, self.view, self.mus, self.download_name)
682                self.view.redirect(
683                    self.view.url(
684                        self.context, self.view.__name__) + self.tab_redirect)
685            else:
686                self.view.flash(_('No local file selected.'))
687                self.view.redirect(
688                    self.view.url(
689                        self.context, self.view.__name__) + self.tab_redirect)
690        return
691
692class PassportDisplay(FileDisplay):
693    """Passport display viewlet.
694    """
695    grok.order(1)
696    grok.context(IStudent)
697    grok.view(StudentBaseDisplayFormPage)
698    grok.require('waeup.viewStudent')
699    grok.template('imagedisplay')
700    label = _(u'Passport Picture')
701    download_name = u'passport.jpg'
702
703class PassportUploadManage(FileUpload):
704    """Passport upload viewlet for officers.
705    """
706    grok.order(1)
707    grok.context(IStudent)
708    grok.view(StudentBaseManageFormPage)
709    grok.require('waeup.manageStudent')
710    grok.template('imageupload')
711    label = _(u'Passport Picture (jpg only)')
712    mus = 1024 * 50
713    download_name = u'passport.jpg'
714    tab_redirect = '?tab2'
715
716class PassportUploadEdit(PassportUploadManage):
717    """Passport upload viewlet for students.
718    """
719    grok.view(StudentFilesUploadPage)
720    grok.require('waeup.uploadStudentFile')
721
722class BirthCertificateDisplay(FileDisplay):
723    """Birth Certificate display viewlet.
724    """
725    grok.order(1)
726    label = _(u'Birth Certificate')
727    title = _(u'Birth Certificate Scan')
728    download_name = u'birth_certificate'
729
730class BirthCertificateSlip(BirthCertificateDisplay):
731    grok.view(ExportPDFClearanceSlipPage)
732
733class BirthCertificateUpload(FileUpload):
734    """Birth Certificate upload viewlet.
735    """
736    grok.order(1)
737    label = _(u'Birth Certificate')
738    title = _(u'Birth Certificate Scan')
739    mus = 1024 * 150
740    download_name = u'birth_certificate'
741    tab_redirect = '?tab2'
742
743class AcceptanceLetterDisplay(FileDisplay):
744    """Acceptance Letter display viewlet.
745    """
746    grok.order(1)
747    label = _(u'Acceptance Letter')
748    title = _(u'Acceptance Letter Scan')
749    download_name = u'acc_let'
750
751class AcceptanceLetterSlip(AcceptanceLetterDisplay):
752    grok.view(ExportPDFClearanceSlipPage)
753
754class AcceptanceLetterUpload(FileUpload):
755    """AcceptanceLetter upload viewlet.
756    """
757    grok.order(2)
758    label = _(u'Acceptance Letter')
759    title = _(u'Acceptance Letter Scan')
760    mus = 1024 * 150
761    download_name = u'acc_let'
762    tab_redirect = '?tab2'
763
764class Image(grok.View):
765    """Renders images for students.
766    """
767    grok.baseclass()
768    grok.name('none.jpg')
769    grok.context(IStudent)
770    grok.require('waeup.viewStudent')
771    download_name = u'none.jpg'
772
773    def render(self):
774        # A filename chooser turns a context into a filename suitable
775        # for file storage.
776        image = getUtility(IExtFileStore).getFileByContext(
777            self.context, attr=self.download_name)
778        if image is None:
779            # show placeholder image
780            self.response.setHeader('Content-Type', 'image/jpeg')
781            return open(DEFAULT_IMAGE_PATH, 'rb').read()
782        dummy,ext = os.path.splitext(image.name)
783        if ext == '.jpg':
784            self.response.setHeader('Content-Type', 'image/jpeg')
785        elif ext == '.png':
786            self.response.setHeader('Content-Type', 'image/png')
787        elif ext == '.pdf':
788            self.response.setHeader('Content-Type', 'application/pdf')
789        elif ext == '.tif':
790            self.response.setHeader('Content-Type', 'image/tiff')
791        return image
792
793class Passport(Image):
794    """Renders jpeg passport picture.
795    """
796    grok.name('passport.jpg')
797    download_name = u'passport.jpg'
798    grok.context(IStudent)
799
800class ApplicationSlipImage(Image):
801    """Renders application slip scan.
802    """
803    grok.name('application_slip')
804    download_name = u'application_slip'
805
806class BirthCertificateImage(Image):
807    """Renders birth certificate scan.
808    """
809    grok.name('birth_certificate')
810    download_name = u'birth_certificate'
811
812class AcceptanceLetterImage(Image):
813    """Renders acceptance letter scan.
814    """
815    grok.name('acc_let')
816    download_name = u'acc_let'
Note: See TracBrowser for help on using the repository browser.