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

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

Add buttons and views for activating and deactivating student accounts.

Add history messages and log entries when students are being activated or deactivated.

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