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

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

Rename course referrers to certificate courses (according to the discussion long time ago).

Edit some button labels and titles.

Move code from view to content components.

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