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

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

Add view buttons and fix test.

  • Property svn:keywords set to Id
File size: 26.0 KB
RevLine 
[7191]1## $Id: viewlets.py 8119 2012-04-12 06:54:46Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
[7106]18import os
[6642]19import grok
[7097]20from zope.component import getUtility
[6642]21from zope.interface import Interface
[7741]22from zope.i18n import translate
[7811]23from waeup.kofa.interfaces import (
[7819]24    IKofaObject, IExtFileStore, IFileStoreNameChooser, IKofaUtils)
[7811]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 (
[7591]29    PrimaryNavTab, ManageActionButton, AddActionButton)
[8106]30from waeup.kofa.browser.layout import (
31    default_primary_nav_template,
32    default_filedisplay_template, default_fileupload_template)
[7811]33from waeup.kofa.students.workflow import (ADMITTED, PAID,
[7591]34    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED)
[7811]35from waeup.kofa.students.browser import (
[7591]36    StudentClearanceManageFormPage,
37    write_log_message, StudentBaseManageFormPage,
38    StudentFilesUploadPage, ExportPDFClearanceSlipPage, StudentsContainerPage,
39    StudentsContainerManagePage, StudentBaseDisplayFormPage,
40    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
41    StudyCourseDisplayFormPage, StudyLevelDisplayFormPage,
42    CourseTicketDisplayFormPage, OnlinePaymentDisplayFormPage,
[8119]43    AccommodationManageFormPage, BedTicketDisplayFormPage,
44    StudentClearanceEditFormPage, StudentPersonalEditFormPage)
[7811]45from waeup.kofa.students.interfaces import (
[7993]46    IStudentsContainer, IStudent,
[7591]47    IStudentStudyCourse, IStudentAccommodation, IStudentStudyLevel,
48    ICourseTicket, IStudentOnlinePayment, IBedTicket,
49    )
[6642]50
[7811]51from waeup.kofa.interfaces import MessageFactory as _
[7674]52
[7819]53grok.context(IKofaObject) # Make IKofaObject the default context
[6687]54grok.templatedir('browser_templates')
[6642]55
[7123]56ALLOWED_FILE_EXTENSIONS = ('jpg', 'png', 'pdf', 'tif')
57
[6687]58class StudentManageSidebar(grok.ViewletManager):
59    grok.name('left_studentmanage')
[6642]60
[6687]61class StudentManageLink(grok.Viewlet):
[6660]62    """A link displayed in the student box which shows up for StudentNavigation
[6642]63    objects.
64
65    """
66    grok.baseclass()
[6687]67    grok.viewletmanager(StudentManageSidebar)
[7819]68    grok.context(IKofaObject)
[6642]69    grok.view(Interface)
70    grok.order(5)
[6660]71    grok.require('waeup.viewStudent')
[6642]72
73    link = 'index'
[7738]74    text = _(u'Base Data')
[6642]75
76    def render(self):
77        url = self.view.url(self.context.getStudent(), self.link)
[7833]78        # Here we know that the cookie has been set
79        lang = self.request.cookies.get('kofa.language')
[7811]80        text = translate(self.text, 'waeup.kofa',
[7741]81            target_language=lang)
[7459]82        return u'<li><a href="%s">%s</a></li>' % (
[7741]83                url, text)
[6642]84
[7459]85class StudentManageApplicationLink(StudentManageLink):
[6687]86    grok.order(1)
[7351]87    link = 'application_slip'
[7738]88    text = _(u'Application Slip')
[7340]89
90    def render(self):
[7351]91        slip = getUtility(IExtFileStore).getFileByContext(
92            self.context.getStudent(), attr=self.link)
93        if slip:
94            url = self.view.url(self.context,self.link)
[7459]95            return u'<li><a href="%s">%s</a></li>' % (
[7340]96                    url, self.text)
97        return ''
98
[7459]99class StudentManageBaseLink(StudentManageLink):
100    grok.order(2)
101    link = 'index'
[7738]102    text = _(u'Base Data')
[7459]103
[6687]104class StudentManageClearanceLink(StudentManageLink):
[7340]105    grok.order(3)
[6687]106    link = 'view_clearance'
[7738]107    text = _(u'Clearance Data')
[6687]108
109class StudentManagePersonalLink(StudentManageLink):
[7340]110    grok.order(4)
[6687]111    link = 'view_personal'
[7738]112    text = _(u'Personal Data')
[6687]113
114class StudentManageStudyCourseLink(StudentManageLink):
[7340]115    grok.order(5)
[6687]116    link = 'studycourse'
[7738]117    text = _(u'Study Course')
[6687]118
119class StudentManagePaymentsLink(StudentManageLink):
[7340]120    grok.order(6)
[7181]121    grok.require('waeup.payStudent')
[6687]122    link = 'payments'
[7738]123    text = _(u'Payments')
[6687]124
125class StudentManageAccommodationLink(StudentManageLink):
[7340]126    grok.order(7)
[7181]127    grok.require('waeup.handleAccommodation')
[6687]128    link = 'accommodation'
[7738]129    text = _(u'Accommodation')
[6687]130
131class StudentManageHistoryLink(StudentManageLink):
[7340]132    grok.order(8)
[6687]133    link = 'history'
[7738]134    text = _(u'History')
[6687]135
[7591]136
137class StudentsContainerManageActionButton(ManageActionButton):
138    grok.order(1)
139    grok.context(IStudentsContainer)
140    grok.view(StudentsContainerPage)
141    grok.require('waeup.manageStudent')
[7738]142    text = _('Manage student section')
[7591]143
144class StudentsContainerAddActionButton(AddActionButton):
145    grok.order(1)
146    grok.context(IStudentsContainer)
147    grok.view(StudentsContainerManagePage)
148    grok.require('waeup.manageStudent')
[7738]149    text = _('Add student')
[7591]150    target = 'addstudent'
151
152class ContactActionButton(ManageActionButton):
153    grok.order(4)
154    grok.context(IStudent)
155    grok.view(StudentBaseDisplayFormPage)
156    grok.require('waeup.manageStudent')
157    icon = 'actionicon_mail.png'
[7738]158    text = _('Send email')
[7591]159    target = 'contactstudent'
160
161class StudentBaseManageActionButton(ManageActionButton):
162    grok.order(1)
163    grok.context(IStudent)
164    grok.view(StudentBaseDisplayFormPage)
165    grok.require('waeup.manageStudent')
[7738]166    text = _('Manage')
[7591]167    target = 'manage_base'
168
169class StudentClearanceManageActionButton(ManageActionButton):
170    grok.order(1)
171    grok.context(IStudent)
172    grok.view(StudentClearanceDisplayFormPage)
173    grok.require('waeup.manageStudent')
[7738]174    text = _('Manage')
[8119]175    target = 'manage_clearance'
[7591]176
177class StudentClearActionButton(ManageActionButton):
178    grok.order(2)
179    grok.context(IStudent)
180    grok.view(StudentClearanceDisplayFormPage)
181    grok.require('waeup.clearStudent')
[7738]182    text = _('Clear student')
[7591]183    target = 'clear'
184    icon = 'actionicon_accept.png'
185
186    @property
187    def target_url(self):
188        if self.context.state != REQUESTED:
189            return ''
190        return self.view.url(self.view.context, self.target)
191
192class StudentRejectClearanceActionButton(ManageActionButton):
193    grok.order(3)
194    grok.context(IStudent)
195    grok.view(StudentClearanceDisplayFormPage)
196    grok.require('waeup.clearStudent')
[7738]197    text = _('Reject clearance')
[7591]198    target = 'reject_clearance'
199    icon = 'actionicon_reject.png'
200
201    @property
202    def target_url(self):
203        if self.context.state not in (REQUESTED, CLEARED):
204            return ''
205        return self.view.url(self.view.context, self.target)
206
207class ClearanceSlipActionButton(ManageActionButton):
208    grok.order(4)
209    grok.context(IStudent)
210    grok.view(StudentClearanceDisplayFormPage)
211    grok.require('waeup.viewStudent')
212    icon = 'actionicon_pdf.png'
[7738]213    text = _('Download clearance slip')
[7591]214    target = 'clearance.pdf'
215
[8119]216class ClearanceViewActionButton(ManageActionButton):
217    grok.order(1)
218    grok.context(IStudent)
219    grok.view(StudentClearanceEditFormPage)
220    grok.require('waeup.viewStudent')
221    icon = 'actionicon_view.png'
222    text = _('View')
223    target = 'view_clearance'
224
225class PersonalViewActionButton(ManageActionButton):
226    grok.order(1)
227    grok.context(IStudent)
228    grok.view(StudentPersonalEditFormPage)
229    grok.require('waeup.viewStudent')
230    icon = 'actionicon_view.png'
231    text = _('View')
232    target = 'view_personal'
233
[7591]234class StudentPersonalEditActionButton(ManageActionButton):
235    grok.order(1)
236    grok.context(IStudent)
237    grok.view(StudentPersonalDisplayFormPage)
238    grok.require('waeup.viewStudent')
[7738]239    text = _('Edit')
[7591]240    target = 'edit_personal'
241
242class StudyCourseManageActionButton(ManageActionButton):
243    grok.order(1)
244    grok.context(IStudentStudyCourse)
245    grok.view(StudyCourseDisplayFormPage)
246    grok.require('waeup.manageStudent')
[7738]247    text = _('Manage')
[7591]248    target = 'manage'
249
[8078]250class StudyLevelManageActionButton(ManageActionButton):
[7591]251    grok.order(1)
252    grok.context(IStudentStudyLevel)
253    grok.view(StudyLevelDisplayFormPage)
254    grok.require('waeup.manageStudent')
[7738]255    text = _('Manage')
[7591]256    target = 'manage'
257
258class StudentValidateCoursesActionButton(ManageActionButton):
259    grok.order(3)
260    grok.context(IStudentStudyLevel)
261    grok.view(StudyLevelDisplayFormPage)
262    grok.require('waeup.validateStudent')
[7738]263    text = _('Validate courses')
[7591]264    target = 'validate_courses'
265    icon = 'actionicon_accept.png'
266
267    @property
268    def target_url(self):
269        if self.context.getStudent().state != REGISTERED or \
270            str(self.context.__parent__.current_level) != self.context.__name__:
271            return ''
272        return self.view.url(self.view.context, self.target)
273
274class StudentRejectCoursesActionButton(ManageActionButton):
275    grok.order(4)
276    grok.context(IStudentStudyLevel)
277    grok.view(StudyLevelDisplayFormPage)
278    grok.require('waeup.validateStudent')
[7738]279    text = _('Reject courses')
[7591]280    target = 'reject_courses'
281    icon = 'actionicon_reject.png'
282
283    @property
284    def target_url(self):
285        if self.context.getStudent().state not in (VALIDATED, REGISTERED) or \
286            str(self.context.__parent__.current_level) != self.context.__name__:
287            return ''
288        return self.view.url(self.view.context, self.target)
289
[8078]290class CourseRegistrationSlipActionButton(ManageActionButton):
291    grok.order(5)
292    grok.context(IStudentStudyLevel)
293    grok.view(StudyLevelDisplayFormPage)
294    grok.require('waeup.viewStudent')
295    icon = 'actionicon_pdf.png'
296    text = _('Download course registration slip')
297    target = 'course_registration.pdf'
298
[7591]299class CourseTicketManageActionButton(ManageActionButton):
300    grok.order(1)
301    grok.context(ICourseTicket)
302    grok.view(CourseTicketDisplayFormPage)
303    grok.require('waeup.manageStudent')
[7738]304    text = _('Manage')
[7591]305    target = 'manage'
306
307#class OnlinePaymentManageActionButton(ManageActionButton):
308#    grok.order(1)
309#    grok.context(IStudentPaymentsContainer)
310#    grok.view(PaymentsDisplayFormPage)
311#    grok.require('waeup.manageStudent')
312#    text = 'Manage payments'
313#    target = 'manage'
314
315class PaymentReceiptActionButton(ManageActionButton):
316    grok.order(1)
317    grok.context(IStudentOnlinePayment)
318    grok.view(OnlinePaymentDisplayFormPage)
319    grok.require('waeup.viewStudent')
320    icon = 'actionicon_pdf.png'
[7738]321    text = _('Download payment receipt')
[7591]322    target = 'payment_receipt.pdf'
323
324    @property
325    def target_url(self):
326        if self.context.p_state != 'paid':
327            return ''
328        return self.view.url(self.view.context, self.target)
329
330class RequestCallbackActionButton(ManageActionButton):
331    grok.order(2)
332    grok.context(IStudentOnlinePayment)
333    grok.view(OnlinePaymentDisplayFormPage)
334    grok.require('waeup.payStudent')
335    icon = 'actionicon_call.png'
[7738]336    text = _('Request callback')
[7997]337    target = 'simulate_callback'
[7591]338
[7997]339    # This button must be neutralized
340    # in the customization package.
[7591]341    @property
342    def target_url(self):
[7888]343        if self.context.p_state == 'paid':
[7591]344            return ''
345        return self.view.url(self.view.context, self.target)
346
347class AddBedTicketActionButton(ManageActionButton):
348    grok.order(1)
349    grok.context(IStudentAccommodation)
350    grok.view(AccommodationManageFormPage)
351    grok.require('waeup.handleAccommodation')
352    icon = 'actionicon_home.png'
[7738]353    text = _('Book accommodation')
[7591]354    target = 'add'
355
356class BedTicketSlipActionButton(ManageActionButton):
357    grok.order(1)
358    grok.context(IBedTicket)
359    grok.view(BedTicketDisplayFormPage)
360    grok.require('waeup.handleAccommodation')
361    icon = 'actionicon_pdf.png'
[7738]362    text = _('Download bed allocation slip')
[7591]363    target = 'bed_allocation.pdf'
364
365class RelocateStudentActionButton(ManageActionButton):
366    grok.order(2)
367    grok.context(IBedTicket)
368    grok.view(BedTicketDisplayFormPage)
369    grok.require('waeup.manageHostels')
370    icon = 'actionicon_reload.png'
[7738]371    text = _('Relocate student')
[7591]372    target = 'relocate'
373
374class StudentBaseActionButton(ManageActionButton):
375    grok.order(1)
376    grok.context(IStudent)
377    grok.view(StudentBaseDisplayFormPage)
378    grok.require('waeup.handleStudent')
[7876]379    text = _('Edit')
[7591]380    target = 'edit_base'
381
382class StudentPasswordActionButton(ManageActionButton):
383    grok.order(2)
384    grok.context(IStudent)
385    grok.view(StudentBaseDisplayFormPage)
386    grok.require('waeup.handleStudent')
387    icon = 'actionicon_key.png'
[7738]388    text = _('Change password')
[7591]389    target = 'change_password'
390
391class StudentPassportActionButton(ManageActionButton):
392    grok.order(3)
393    grok.context(IStudent)
394    grok.view(StudentBaseDisplayFormPage)
395    grok.require('waeup.handleStudent')
396    icon = 'actionicon_portrait.png'
[7738]397    text = _('Change portrait')
[7591]398    target = 'change_portrait'
399
400    @property
401    def target_url(self):
[7671]402        if self.context.state != ADMITTED:
[7591]403            return ''
404        return self.view.url(self.view.context, self.target)
405
406class StudentClearanceStartActionButton(ManageActionButton):
407    grok.order(1)
408    grok.context(IStudent)
409    grok.view(StudentClearanceDisplayFormPage)
410    grok.require('waeup.handleStudent')
411    icon = 'actionicon_start.gif'
[7738]412    text = _('Start clearance')
[7591]413    target = 'start_clearance'
414
415    @property
416    def target_url(self):
[7671]417        if self.context.state != ADMITTED:
[7591]418            return ''
419        return self.view.url(self.view.context, self.target)
420
421class StudentClearanceEditActionButton(ManageActionButton):
422    grok.order(1)
423    grok.context(IStudent)
424    grok.view(StudentClearanceDisplayFormPage)
425    grok.require('waeup.handleStudent')
[7738]426    text = _('Edit')
[7591]427    target = 'cedit'
428
429    @property
430    def target_url(self):
431        if self.context.clearance_locked:
432            return ''
433        return self.view.url(self.view.context, self.target)
434
435class CourseRegistrationStartActionButton(ManageActionButton):
436    grok.order(1)
437    grok.context(IStudentStudyCourse)
438    grok.view(StudyCourseDisplayFormPage)
439    grok.require('waeup.handleStudent')
440    icon = 'actionicon_start.gif'
[7738]441    text = _('Start course registration')
[7591]442    target = 'start_course_registration'
443
444    @property
445    def target_url(self):
446        if not self.context.getStudent().state in (CLEARED,RETURNING):
447            return ''
448        return self.view.url(self.view.context, self.target)
449
450class AddStudyLevelActionButton(AddActionButton):
451    grok.order(1)
452    grok.context(IStudentStudyCourse)
453    grok.view(StudyCourseDisplayFormPage)
454    grok.require('waeup.handleStudent')
[7738]455    text = _('Add course list')
[7591]456    target = 'add'
457
458    @property
459    def target_url(self):
460        student = self.view.context.getStudent()
[7671]461        condition1 = student.state != PAID
[7591]462        condition2 = str(student['studycourse'].current_level) in \
463            self.view.context.keys()
464        if condition1 or condition2:
465            return ''
466        return self.view.url(self.view.context, self.target)
467
468class StudyLevelEditActionButton(ManageActionButton):
[8078]469    grok.order(2)
[7591]470    grok.context(IStudentStudyLevel)
471    grok.view(StudyLevelDisplayFormPage)
472    grok.require('waeup.handleStudent')
[7738]473    text = _('Add and remove courses')
[7591]474    target = 'edit'
475
476    @property
477    def target_url(self):
478        student = self.view.context.getStudent()
[7671]479        condition1 = student.state != PAID
[7591]480        condition2 = student[
481            'studycourse'].current_level != self.view.context.level
482        if condition1 or condition2:
483            return ''
484        return self.view.url(self.view.context, self.target)
485
[7184]486class StudentsTab(PrimaryNavTab):
487    """Students tab in primary navigation.
488    """
489
[7819]490    grok.context(IKofaObject)
[7184]491    grok.order(4)
[7240]492    grok.require('waeup.viewStudentsTab')
[7184]493
494    pnav = 4
[7674]495    tab_title = _(u'Students')
[7184]496
497    @property
498    def link_target(self):
499        return self.view.application_url('students')
500
[6687]501class PrimaryStudentNavManager(grok.ViewletManager):
502    """Viewlet manager for the primary navigation tab.
503    """
504    grok.name('primary_nav_student')
505
506class PrimaryStudentNavTab(grok.Viewlet):
507    """Base for primary student nav tabs.
508    """
509    grok.baseclass()
510    grok.viewletmanager(PrimaryStudentNavManager)
[7243]511    template = default_primary_nav_template
[6687]512    grok.order(1)
[7184]513    grok.require('waeup.Authenticated')
[6687]514    pnav = 0
515    tab_title = u'Some Text'
516
517    @property
518    def link_target(self):
519        return self.view.application_url()
520
521    @property
522    def active(self):
523        view_pnav = getattr(self.view, 'pnav', 0)
524        if view_pnav == self.pnav:
525            return 'active'
526        return ''
527
[7240]528class MyStudentDataTab(PrimaryStudentNavTab):
[7459]529    """MyData dropdown tab in primary navigation.
[6687]530    """
531    grok.order(3)
[7240]532    grok.require('waeup.viewMyStudentDataTab')
[7459]533    grok.template('mydatadropdowntabs')
[6687]534    pnav = 4
[7738]535    tab_title = _(u'My Data')
[6687]536
537    @property
[7459]538    def active(self):
539        view_pnav = getattr(self.view, 'pnav', 0)
540        if view_pnav == self.pnav:
541            return 'active dropdown'
542        return 'dropdown'
[7097]543
[7459]544    @property
545    def targets(self):
546        student_url = self.view.application_url() + (
547            '/students/%s' % self.request.principal.id)
548        #app_slip = getUtility(IExtFileStore).getFileByContext(
549        #    self.context.getStudent(), 'application_slip')
550        targets = []
551        #if app_slip:
552        #    targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
553        targets += [
554            {'url':student_url, 'title':'Base Data'},
[7738]555            {'url':student_url + '/view_clearance', 'title':_('Clearance Data')},
556            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
557            {'url':student_url + '/studycourse', 'title':_('Study Course')},
558            {'url':student_url + '/payments', 'title':_('Payments')},
559            {'url':student_url + '/accommodation', 'title':_('Accommodation Data')},
560            {'url':student_url + '/history', 'title':_('History')},
[7459]561            ]
562        return targets
563
[7107]564def handle_file_delete(context, view, download_name):
565    """Handle deletion of student file.
566
567    """
568    store = getUtility(IExtFileStore)
569    store.deleteFileByContext(context, attr=download_name)
[7108]570    write_log_message(view, 'deleted: %s' % download_name)
[7738]571    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
[7107]572    return
573
[7106]574def handle_file_upload(upload, context, view, max_size, download_name=None):
575    """Handle upload of student file.
[7097]576
577    Returns `True` in case of success or `False`.
578
579    Please note that file pointer passed in (`upload`) most probably
580    points to end of file when leaving this function.
581    """
[7106]582    # Check some file requirements first
583    if upload.filename.count('.') == 0:
[7738]584        view.flash(_('File name has no extension.'))
[7106]585        return False
586    if upload.filename.count('.') > 1:
[7738]587        view.flash(_('File name contains more than one dot.'))
[7106]588        return False
589    basename, expected_ext = os.path.splitext(download_name)
590    dummy, ext = os.path.splitext(upload.filename)
591    ext.lower()
[7123]592    if expected_ext:
593        if ext != expected_ext:
[7738]594            view.flash(_('${a} file extension expected.',
595                mapping = {'a':expected_ext.replace('.','')}))
[7123]596            return False
597    else:
598        if not ext.replace('.','') in ALLOWED_FILE_EXTENSIONS:
599            view.flash(
[7738]600                _('Only the following extension are allowed: ${a}',
601                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
[7123]602            return False
603        download_name += ext
[7097]604    size = file_size(upload)
605    if size > max_size:
[7738]606        view.flash(_('Uploaded file is too big.'))
[7097]607        return False
608    upload.seek(0) # file pointer moved when determining size
609    store = getUtility(IExtFileStore)
[7106]610    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
[7097]611    store.createFile(file_id, upload)
[7108]612    write_log_message(view, 'uploaded: %s (%s)' % (download_name,upload.filename))
[7738]613    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
[7097]614    return True
615
616class FileManager(grok.ViewletManager):
617    """Viewlet manager for uploading files, preferably scanned images.
618    """
619    grok.name('files')
620
621class FileDisplay(grok.Viewlet):
622    """Base file display viewlet.
623    """
624    grok.baseclass()
[7993]625    grok.context(IStudent)
[7097]626    grok.viewletmanager(FileManager)
627    grok.view(StudentClearanceDisplayFormPage)
[8106]628    template = default_filedisplay_template
[7097]629    grok.order(1)
630    grok.require('waeup.viewStudent')
[7738]631    label = _(u'File')
632    title = _(u'Scan')
[7106]633    download_name = u'filename.jpg'
[7097]634
[7107]635    @property
636    def file_exists(self):
637        image = getUtility(IExtFileStore).getFileByContext(
638            self.context, attr=self.download_name)
639        if image:
640            return True
641        else:
642            return False
643
[7097]644class FileUpload(FileDisplay):
645    """Base upload viewlet.
646    """
647    grok.baseclass()
[7993]648    grok.context(IStudent)
[7097]649    grok.viewletmanager(FileManager)
650    grok.view(StudentClearanceManageFormPage)
[8106]651    template = default_fileupload_template
[7127]652    grok.require('waeup.uploadStudentFile')
[7491]653    tab_redirect = '?tab2'
[7097]654    mus = 1024 * 150
[7735]655    upload_button =_('Upload new file')
656    delete_button = _('Delete attachment')
[7097]657
[7117]658    @property
659    def input_name(self):
660        return "%s" % self.__name__
661
[7097]662    def update(self):
663        self.max_upload_size = string_from_bytes(self.mus)
[7117]664        delete_button = self.request.form.get(
665            'delete_%s' % self.input_name, None)
666        upload_button = self.request.form.get(
667            'upload_%s' % self.input_name, None)
[7108]668        if delete_button:
[7107]669            handle_file_delete(
670                context=self.context, view=self.view,
671                download_name=self.download_name)
672            self.view.redirect(
[7134]673                self.view.url(
674                    self.context, self.view.__name__) + self.tab_redirect)
[7107]675            return
[7108]676        if upload_button:
677            upload = self.request.form.get(self.input_name, None)
678            if upload:
679                # We got a fresh upload
[7111]680                handle_file_upload(upload,
681                    self.context, self.view, self.mus, self.download_name)
682                self.view.redirect(
[7134]683                    self.view.url(
684                        self.context, self.view.__name__) + self.tab_redirect)
[7117]685            else:
[7738]686                self.view.flash(_('No local file selected.'))
[7117]687                self.view.redirect(
[7134]688                    self.view.url(
689                        self.context, self.view.__name__) + self.tab_redirect)
[7097]690        return
691
[7112]692class PassportDisplay(FileDisplay):
693    """Passport display viewlet.
694    """
695    grok.order(1)
696    grok.context(IStudent)
697    grok.view(StudentBaseDisplayFormPage)
698    grok.require('waeup.viewStudent')
699    grok.template('imagedisplay')
[7738]700    label = _(u'Passport Picture')
[7112]701    download_name = u'passport.jpg'
702
703class PassportUploadManage(FileUpload):
704    """Passport upload viewlet for officers.
705    """
706    grok.order(1)
707    grok.context(IStudent)
708    grok.view(StudentBaseManageFormPage)
[7136]709    grok.require('waeup.manageStudent')
[7112]710    grok.template('imageupload')
[7738]711    label = _(u'Passport Picture (jpg only)')
[7112]712    mus = 1024 * 50
713    download_name = u'passport.jpg'
[7491]714    tab_redirect = '?tab2'
[7112]715
716class PassportUploadEdit(PassportUploadManage):
717    """Passport upload viewlet for students.
718    """
[7114]719    grok.view(StudentFilesUploadPage)
[7127]720    grok.require('waeup.uploadStudentFile')
[7112]721
[7097]722class BirthCertificateDisplay(FileDisplay):
[7112]723    """Birth Certificate display viewlet.
[7097]724    """
725    grok.order(1)
[7738]726    label = _(u'Birth Certificate')
727    title = _(u'Birth Certificate Scan')
[7123]728    download_name = u'birth_certificate'
[7097]729
[7280]730class BirthCertificateSlip(BirthCertificateDisplay):
731    grok.view(ExportPDFClearanceSlipPage)
732
[7127]733class BirthCertificateUpload(FileUpload):
[7097]734    """Birth Certificate upload viewlet.
735    """
736    grok.order(1)
[7738]737    label = _(u'Birth Certificate')
738    title = _(u'Birth Certificate Scan')
[7097]739    mus = 1024 * 150
[7123]740    download_name = u'birth_certificate'
[7491]741    tab_redirect = '?tab2'
[7097]742
[7111]743class AcceptanceLetterDisplay(FileDisplay):
[7112]744    """Acceptance Letter display viewlet.
[7111]745    """
746    grok.order(1)
[7738]747    label = _(u'Acceptance Letter')
748    title = _(u'Acceptance Letter Scan')
[8109]749    download_name = u'acc_let'
[7111]750
[7280]751class AcceptanceLetterSlip(AcceptanceLetterDisplay):
752    grok.view(ExportPDFClearanceSlipPage)
753
[7127]754class AcceptanceLetterUpload(FileUpload):
[7111]755    """AcceptanceLetter upload viewlet.
756    """
[7112]757    grok.order(2)
[7738]758    label = _(u'Acceptance Letter')
759    title = _(u'Acceptance Letter Scan')
[7111]760    mus = 1024 * 150
[8109]761    download_name = u'acc_let'
[7491]762    tab_redirect = '?tab2'
[7111]763
[7097]764class Image(grok.View):
[7351]765    """Renders images for students.
[7097]766    """
[7106]767    grok.baseclass()
[7097]768    grok.name('none.jpg')
[7993]769    grok.context(IStudent)
[7097]770    grok.require('waeup.viewStudent')
[7106]771    download_name = u'none.jpg'
[7097]772
773    def render(self):
774        # A filename chooser turns a context into a filename suitable
775        # for file storage.
776        image = getUtility(IExtFileStore).getFileByContext(
[7106]777            self.context, attr=self.download_name)
[7097]778        if image is None:
779            # show placeholder image
[7123]780            self.response.setHeader('Content-Type', 'image/jpeg')
[7097]781            return open(DEFAULT_IMAGE_PATH, 'rb').read()
[7123]782        dummy,ext = os.path.splitext(image.name)
783        if ext == '.jpg':
784            self.response.setHeader('Content-Type', 'image/jpeg')
785        elif ext == '.png':
786            self.response.setHeader('Content-Type', 'image/png')
787        elif ext == '.pdf':
788            self.response.setHeader('Content-Type', 'application/pdf')
789        elif ext == '.tif':
790            self.response.setHeader('Content-Type', 'image/tiff')
[7097]791        return image
792
[7112]793class Passport(Image):
794    """Renders jpeg passport picture.
795    """
796    grok.name('passport.jpg')
797    download_name = u'passport.jpg'
798    grok.context(IStudent)
799
[7351]800class ApplicationSlipImage(Image):
801    """Renders application slip scan.
802    """
803    grok.name('application_slip')
804    download_name = u'application_slip'
805
[7097]806class BirthCertificateImage(Image):
[7351]807    """Renders birth certificate scan.
[7097]808    """
[7123]809    grok.name('birth_certificate')
810    download_name = u'birth_certificate'
[7111]811
812class AcceptanceLetterImage(Image):
[7351]813    """Renders acceptance letter scan.
[7111]814    """
[8109]815    grok.name('acc_let')
816    download_name = u'acc_let'
Note: See TracBrowser for help on using the repository browser.