source: main/waeup.kofa/branches/uli-async-update/src/waeup/kofa/students/viewlets.py @ 9208

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

Merge changes from trunk r9171:9207.

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