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

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

Protect StudyLevelEditFormPage? and CourseTicketAddFormPage2. Students are not allowed to edit study levels which are not current.

  • Property svn:keywords set to Id
File size: 27.8 KB
Line 
13## $Id: viewlets.py 9257 2012-09-28 19:47:52Z 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(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 = self.view.context.is_current_level
569        is_current = self.context.__parent__.is_current
570        if condition1 and condition2 and is_current:
571            return self.view.url(self.view.context, self.target)
572        return ''
573
574class StudentsTab(PrimaryNavTab):
575    """Students tab in primary navigation.
576    """
577
578    grok.context(IKofaObject)
579    grok.order(4)
580    grok.require('waeup.viewStudentsTab')
581
582    pnav = 4
583    tab_title = _(u'Students')
584
585    @property
586    def link_target(self):
587        return self.view.application_url('students')
588
589class PrimaryStudentNavManager(grok.ViewletManager):
590    """Viewlet manager for the primary navigation tab.
591    """
592    grok.name('primary_nav_student')
593
594class PrimaryStudentNavTab(grok.Viewlet):
595    """Base for primary student nav tabs.
596    """
597    grok.baseclass()
598    grok.viewletmanager(PrimaryStudentNavManager)
599    template = default_primary_nav_template
600    grok.order(1)
601    grok.require('waeup.Authenticated')
602    pnav = 0
603    tab_title = u'Some Text'
604
605    @property
606    def link_target(self):
607        return self.view.application_url()
608
609    @property
610    def active(self):
611        view_pnav = getattr(self.view, 'pnav', 0)
612        if view_pnav == self.pnav:
613            return 'active'
614        return ''
615
616class MyStudentDataTab(PrimaryStudentNavTab):
617    """MyData dropdown tab in primary navigation.
618    """
619    grok.order(3)
620    grok.require('waeup.viewMyStudentDataTab')
621    grok.template('mydatadropdowntabs')
622    pnav = 4
623    tab_title = _(u'My Data')
624
625    @property
626    def active(self):
627        view_pnav = getattr(self.view, 'pnav', 0)
628        if view_pnav == self.pnav:
629            return 'active dropdown'
630        return 'dropdown'
631
632    @property
633    def targets(self):
634        student = grok.getSite()['students'][self.request.principal.id]
635        student_url = self.view.url(student)
636        app_slip = getUtility(IExtFileStore).getFileByContext(
637            student, 'application_slip')
638        targets = []
639        if app_slip:
640            targets = [{'url':student_url + '/application_slip', 'title':'Application Slip'},]
641        targets += [
642            {'url':student_url, 'title':'Base Data'},
643            {'url':student_url + '/view_clearance',
644             'title':_('Clearance Data')},
645            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
646            {'url':student_url + '/studycourse', 'title':_('Study Course')},
647            {'url':student_url + '/payments', 'title':_('Payments')},
648            {'url':student_url + '/accommodation',
649             'title':_('Accommodation Data')},
650            {'url':student_url + '/history', 'title':_('History')},
651            ]
652        return targets
653
654def handle_file_delete(context, view, download_name):
655    """Handle deletion of student file.
656
657    """
658    store = getUtility(IExtFileStore)
659    store.deleteFileByContext(context, attr=download_name)
660    context.writeLogMessage(view, 'deleted: %s' % download_name)
661    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
662    return
663
664def handle_file_upload(upload, context, view, max_size, download_name=None):
665    """Handle upload of student file.
666
667    Returns `True` in case of success or `False`.
668
669    Please note that file pointer passed in (`upload`) most probably
670    points to end of file when leaving this function.
671    """
672    # Check some file requirements first
673    size = file_size(upload)
674    if size > max_size:
675        view.flash(_('Uploaded file is too big.'))
676        return False
677    upload.seek(0) # file pointer moved when determining size
678    file_format = get_fileformat(None, upload.read(512))
679    upload.seek(0) # same here
680    if file_format is None:
681        view.flash(_('Could not determine file type.'))
682        return False
683    basename, expected_ext = os.path.splitext(download_name)
684    if expected_ext:
685        if '.' + file_format != expected_ext:
686            view.flash(_('${a} file extension expected.',
687                mapping = {'a':expected_ext[1:]}))
688            return False
689    else:
690        if not file_format in ALLOWED_FILE_EXTENSIONS:
691            view.flash(
692                _('Only the following extensions are allowed: ${a}',
693                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
694            return False
695        download_name += '.' + file_format
696    store = getUtility(IExtFileStore)
697    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
698    store.createFile(file_id, upload)
699    context.writeLogMessage(view, 'uploaded: %s (%s)' % (
700        download_name,upload.filename))
701    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
702    return True
703
704class FileManager(grok.ViewletManager):
705    """Viewlet manager for uploading files, preferably scanned images.
706    """
707    grok.name('files')
708
709class FileDisplay(grok.Viewlet):
710    """Base file display viewlet.
711    """
712    grok.baseclass()
713    grok.context(IStudent)
714    grok.viewletmanager(FileManager)
715    grok.view(StudentClearanceDisplayFormPage)
716    template = default_filedisplay_template
717    grok.order(1)
718    grok.require('waeup.viewStudent')
719    label = _(u'File')
720    title = _(u'Scan')
721    download_name = u'filename.jpg'
722
723    @property
724    def file_exists(self):
725        image = getUtility(IExtFileStore).getFileByContext(
726            self.context, attr=self.download_name)
727        if image:
728            return True
729        else:
730            return False
731
732class FileUpload(FileDisplay):
733    """Base upload viewlet.
734    """
735    grok.baseclass()
736    grok.context(IStudent)
737    grok.viewletmanager(FileManager)
738    grok.view(StudentClearanceManageFormPage)
739    template = default_fileupload_template
740    grok.require('waeup.uploadStudentFile')
741    tab_redirect = '?tab2'
742    mus = 1024 * 150
743    upload_button =_('Upload new file')
744    delete_button = _('Delete attachment')
745    show_viewlet = True
746
747    @property
748    def input_name(self):
749        return "%s" % self.__name__
750
751    def update(self):
752        self.max_upload_size = string_from_bytes(self.mus)
753        delete_button = self.request.form.get(
754            'delete_%s' % self.input_name, None)
755        upload_button = self.request.form.get(
756            'upload_%s' % self.input_name, None)
757        if delete_button:
758            handle_file_delete(
759                context=self.context, view=self.view,
760                download_name=self.download_name)
761            self.view.redirect(
762                self.view.url(
763                    self.context, self.view.__name__) + self.tab_redirect)
764            return
765        if upload_button:
766            upload = self.request.form.get(self.input_name, None)
767            if upload:
768                # We got a fresh upload
769                handle_file_upload(upload,
770                    self.context, self.view, self.mus, self.download_name)
771                self.view.redirect(
772                    self.view.url(
773                        self.context, self.view.__name__) + self.tab_redirect)
774            else:
775                self.view.flash(_('No local file selected.'))
776                self.view.redirect(
777                    self.view.url(
778                        self.context, self.view.__name__) + self.tab_redirect)
779        return
780
781class PassportDisplay(FileDisplay):
782    """Passport display viewlet.
783    """
784    grok.order(1)
785    grok.context(IStudent)
786    grok.view(StudentBaseDisplayFormPage)
787    grok.require('waeup.viewStudent')
788    grok.template('imagedisplay')
789    label = _(u'Passport Picture')
790    download_name = u'passport.jpg'
791
792class PassportUploadManage(FileUpload):
793    """Passport upload viewlet for officers.
794    """
795    grok.order(1)
796    grok.context(IStudent)
797    grok.view(StudentBaseManageFormPage)
798    grok.require('waeup.manageStudent')
799    grok.template('imageupload')
800    label = _(u'Passport Picture (jpg only)')
801    mus = 1024 * 50
802    download_name = u'passport.jpg'
803    tab_redirect = '?tab2'
804
805class PassportUploadEdit(PassportUploadManage):
806    """Passport upload viewlet for students.
807    """
808    grok.view(StudentFilesUploadPage)
809    grok.require('waeup.uploadStudentFile')
810
811class BirthCertificateDisplay(FileDisplay):
812    """Birth Certificate display viewlet.
813    """
814    grok.order(1)
815    label = _(u'Birth Certificate')
816    title = _(u'Birth Certificate Scan')
817    download_name = u'birth_certificate'
818
819class BirthCertificateSlip(BirthCertificateDisplay):
820    grok.view(ExportPDFClearanceSlipPage)
821
822class BirthCertificateUpload(FileUpload):
823    """Birth Certificate upload viewlet.
824    """
825    grok.order(1)
826    label = _(u'Birth Certificate')
827    title = _(u'Birth Certificate Scan')
828    mus = 1024 * 150
829    download_name = u'birth_certificate'
830    tab_redirect = '?tab2'
831
832class Image(grok.View):
833    """Renders images for students.
834    """
835    grok.baseclass()
836    grok.name('none.jpg')
837    grok.context(IStudent)
838    grok.require('waeup.viewStudent')
839    download_name = u'none.jpg'
840
841    def render(self):
842        # A filename chooser turns a context into a filename suitable
843        # for file storage.
844        image = getUtility(IExtFileStore).getFileByContext(
845            self.context, attr=self.download_name)
846        if image is None:
847            # show placeholder image
848            self.response.setHeader('Content-Type', 'image/jpeg')
849            return open(DEFAULT_IMAGE_PATH, 'rb').read()
850        dummy,ext = os.path.splitext(image.name)
851        if ext == '.jpg':
852            self.response.setHeader('Content-Type', 'image/jpeg')
853        elif ext == '.png':
854            self.response.setHeader('Content-Type', 'image/png')
855        elif ext == '.pdf':
856            self.response.setHeader('Content-Type', 'application/pdf')
857        elif ext == '.tif':
858            self.response.setHeader('Content-Type', 'image/tiff')
859        return image
860
861class Passport(Image):
862    """Renders jpeg passport picture.
863    """
864    grok.name('passport.jpg')
865    download_name = u'passport.jpg'
866    grok.context(IStudent)
867
868class ApplicationSlipImage(Image):
869    """Renders application slip scan.
870    """
871    grok.name('application_slip')
872    download_name = u'application_slip'
873
874class BirthCertificateImage(Image):
875    """Renders birth certificate scan.
876    """
877    grok.name('birth_certificate')
878    download_name = u'birth_certificate'
Note: See TracBrowser for help on using the repository browser.