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

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

Add view buttons and fix test.

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