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

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

Add StudentTransferFormPage?.

Do not show any button on old studycourse (studycourse_1 or studycourse_2) pages.

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