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

Last change on this file since 10805 was 10805, checked in by Henrik Bettermann, 11 years ago

Localize StudentManageApplicationLink? properly.

  • Property svn:keywords set to Id
File size: 32.8 KB
RevLine 
[9138]13## $Id: viewlets.py 10805 2013-11-28 16:50:50Z henrik $
[7191]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 (
[8467]24    IKofaObject, IExtFileStore, IFileStoreNameChooser)
[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 (
[8467]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,
[10458]35    VALIDATED, GRADUATED, TRANSCRIPT)
[7811]36from waeup.kofa.students.browser import (
[9814]37    clearance_disabled_message,
[8735]38    StudentClearanceManageFormPage,
[8467]39    StudentBaseManageFormPage, StudentFilesUploadPage,
40    ExportPDFClearanceSlipPage, StudentsContainerPage,
[7591]41    StudentsContainerManagePage, StudentBaseDisplayFormPage,
42    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
43    StudyCourseDisplayFormPage, StudyLevelDisplayFormPage,
44    CourseTicketDisplayFormPage, OnlinePaymentDisplayFormPage,
[8119]45    AccommodationManageFormPage, BedTicketDisplayFormPage,
[9517]46    StudentClearanceEditFormPage, StudentPersonalEditFormPage,
[10266]47    PaymentsManageFormPage, StudyCourseTranscriptPage)
[7811]48from waeup.kofa.students.interfaces import (
[8467]49    IStudentsContainer, IStudent, IStudentStudyCourse, IStudentAccommodation,
50    IStudentStudyLevel, ICourseTicket, IStudentOnlinePayment, IBedTicket,
[10021]51    IStudentPaymentsContainer, IStudentsUtils
[7591]52    )
[8467]53from waeup.kofa.utils.helpers import get_fileformat
[6642]54
[7819]55grok.context(IKofaObject) # Make IKofaObject the default context
[6687]56grok.templatedir('browser_templates')
[6642]57
[7123]58ALLOWED_FILE_EXTENSIONS = ('jpg', 'png', 'pdf', 'tif')
59
[6687]60class StudentManageSidebar(grok.ViewletManager):
61    grok.name('left_studentmanage')
[6642]62
[6687]63class StudentManageLink(grok.Viewlet):
[6660]64    """A link displayed in the student box which shows up for StudentNavigation
[6642]65    objects.
66
67    """
68    grok.baseclass()
[6687]69    grok.viewletmanager(StudentManageSidebar)
[7819]70    grok.context(IKofaObject)
[6642]71    grok.view(Interface)
72    grok.order(5)
[6660]73    grok.require('waeup.viewStudent')
[6642]74
75    link = 'index'
[7738]76    text = _(u'Base Data')
[6642]77
78    def render(self):
[8736]79        url = self.view.url(self.context.student, self.link)
[7833]80        # Here we know that the cookie has been set
81        lang = self.request.cookies.get('kofa.language')
[7811]82        text = translate(self.text, 'waeup.kofa',
[7741]83            target_language=lang)
[10802]84        if not self.link:
85            return ''
[7459]86        return u'<li><a href="%s">%s</a></li>' % (
[7741]87                url, text)
[6642]88
[7459]89class StudentManageApplicationLink(StudentManageLink):
[6687]90    grok.order(1)
[7351]91    link = 'application_slip'
[7738]92    text = _(u'Application Slip')
[7340]93
94    def render(self):
[7351]95        slip = getUtility(IExtFileStore).getFileByContext(
[8736]96            self.context.student, attr=self.link)
[7351]97        if slip:
[10805]98            lang = self.request.cookies.get('kofa.language')
99            text = translate(self.text, 'waeup.kofa',
100                target_language=lang)
[9397]101            url = self.view.url(self.context.student,self.link)
[7459]102            return u'<li><a href="%s">%s</a></li>' % (
[10805]103                    url, text)
[7340]104        return ''
105
[7459]106class StudentManageBaseLink(StudentManageLink):
107    grok.order(2)
108    link = 'index'
[7738]109    text = _(u'Base Data')
[7459]110
[6687]111class StudentManageClearanceLink(StudentManageLink):
[7340]112    grok.order(3)
[10802]113    grok.name('studentmanageclearancelink')
[6687]114    link = 'view_clearance'
[7738]115    text = _(u'Clearance Data')
[6687]116
117class StudentManagePersonalLink(StudentManageLink):
[7340]118    grok.order(4)
[10802]119    grok.name('studentmanagepersonallink')
[6687]120    link = 'view_personal'
[7738]121    text = _(u'Personal Data')
[6687]122
123class StudentManageStudyCourseLink(StudentManageLink):
[7340]124    grok.order(5)
[6687]125    link = 'studycourse'
[7738]126    text = _(u'Study Course')
[6687]127
128class StudentManagePaymentsLink(StudentManageLink):
[7340]129    grok.order(6)
[10080]130    grok.require('waeup.viewStudent')
[6687]131    link = 'payments'
[7738]132    text = _(u'Payments')
[6687]133
134class StudentManageAccommodationLink(StudentManageLink):
[7340]135    grok.order(7)
[10803]136    grok.name('studentmanageaccommodationlink')
[7181]137    grok.require('waeup.handleAccommodation')
[6687]138    link = 'accommodation'
[7738]139    text = _(u'Accommodation')
[6687]140
141class StudentManageHistoryLink(StudentManageLink):
[7340]142    grok.order(8)
[6687]143    link = 'history'
[7738]144    text = _(u'History')
[6687]145
[7591]146
147class StudentsContainerManageActionButton(ManageActionButton):
148    grok.order(1)
149    grok.context(IStudentsContainer)
150    grok.view(StudentsContainerPage)
151    grok.require('waeup.manageStudent')
[7738]152    text = _('Manage student section')
[7591]153
154class StudentsContainerAddActionButton(AddActionButton):
155    grok.order(1)
156    grok.context(IStudentsContainer)
157    grok.view(StudentsContainerManagePage)
158    grok.require('waeup.manageStudent')
[7738]159    text = _('Add student')
[7591]160    target = 'addstudent'
161
162class ContactActionButton(ManageActionButton):
[9191]163    grok.order(5)
[7591]164    grok.context(IStudent)
165    grok.view(StudentBaseDisplayFormPage)
166    grok.require('waeup.manageStudent')
167    icon = 'actionicon_mail.png'
[7738]168    text = _('Send email')
[7591]169    target = 'contactstudent'
170
171class StudentBaseManageActionButton(ManageActionButton):
172    grok.order(1)
173    grok.context(IStudent)
174    grok.view(StudentBaseDisplayFormPage)
175    grok.require('waeup.manageStudent')
[7738]176    text = _('Manage')
[7591]177    target = 'manage_base'
178
[9273]179class StudentTrigTransActionButton(ManageActionButton):
180    grok.order(2)
181    grok.context(IStudent)
182    grok.view(StudentBaseDisplayFormPage)
183    grok.require('waeup.triggerTransition')
184    icon = 'actionicon_trigtrans.png'
185    text = _(u'Trigger transition')
186    target = 'trigtrans'
187
[9338]188class StudentLoginAsActionButton(ManageActionButton):
189    grok.order(3)
190    grok.context(IStudent)
191    grok.view(StudentBaseDisplayFormPage)
192    grok.require('waeup.loginAsStudent')
193    icon = 'actionicon_mask.png'
194    text = _(u'Login as student')
195    target = 'loginasstep1'
196
[9191]197class AdmissionSlipActionButton(ManageActionButton):
198    grok.order(4)
199    grok.context(IStudent)
200    grok.view(StudentBaseDisplayFormPage)
201    grok.require('waeup.viewStudent')
202    icon = 'actionicon_pdf.png'
203    text = _('Download admission letter')
204    target = 'admission_slip.pdf'
205
[10694]206class StudentTransferButton(ManageActionButton):
[9191]207    grok.order(6)
[9124]208    grok.context(IStudent)
209    grok.view(StudentBaseDisplayFormPage)
210    grok.require('waeup.manageStudent')
[9138]211    text = _('Transfer student')
212    target = 'transfer'
213    icon = 'actionicon_redo.png'
214
215class StudentDeactivateActionButton(ManageActionButton):
[9191]216    grok.order(7)
[9138]217    grok.context(IStudent)
218    grok.view(StudentBaseDisplayFormPage)
219    grok.require('waeup.manageStudent')
[9124]220    text = _('Deactivate account')
221    target = 'deactivate'
222    icon = 'actionicon_traffic_lights_red.png'
223
224    @property
225    def target_url(self):
226        if self.context.suspended:
227            return ''
228        return self.view.url(self.view.context, self.target)
229
[9145]230    @property
231    def onclick(self):
232        return "return window.confirm(%s);" % _(
233            "'A history message will be added. Are you sure?'")
234
[9124]235class StudentActivateActionButton(ManageActionButton):
[9191]236    grok.order(7)
[9124]237    grok.context(IStudent)
238    grok.view(StudentBaseDisplayFormPage)
239    grok.require('waeup.manageStudent')
240    text = _('Activate account')
241    target = 'activate'
242    icon = 'actionicon_traffic_lights_green.png'
243
244    @property
245    def target_url(self):
246        if not self.context.suspended:
247            return ''
248        return self.view.url(self.view.context, self.target)
249
[9145]250    @property
251    def onclick(self):
252        return "return window.confirm(%s);" % _(
253            "'A history message will be added. Are you sure?'")
254
[7591]255class StudentClearanceManageActionButton(ManageActionButton):
256    grok.order(1)
257    grok.context(IStudent)
258    grok.view(StudentClearanceDisplayFormPage)
259    grok.require('waeup.manageStudent')
[7738]260    text = _('Manage')
[8119]261    target = 'manage_clearance'
[7591]262
263class StudentClearActionButton(ManageActionButton):
264    grok.order(2)
265    grok.context(IStudent)
266    grok.view(StudentClearanceDisplayFormPage)
267    grok.require('waeup.clearStudent')
[7738]268    text = _('Clear student')
[7591]269    target = 'clear'
270    icon = 'actionicon_accept.png'
271
272    @property
273    def target_url(self):
[9814]274        if clearance_disabled_message(self.context):
275            return ''
[7591]276        if self.context.state != REQUESTED:
277            return ''
278        return self.view.url(self.view.context, self.target)
279
280class StudentRejectClearanceActionButton(ManageActionButton):
281    grok.order(3)
282    grok.context(IStudent)
283    grok.view(StudentClearanceDisplayFormPage)
284    grok.require('waeup.clearStudent')
[7738]285    text = _('Reject clearance')
[7591]286    target = 'reject_clearance'
287    icon = 'actionicon_reject.png'
288
289    @property
290    def target_url(self):
[9814]291        if clearance_disabled_message(self.context):
292            return ''
[7591]293        if self.context.state not in (REQUESTED, CLEARED):
294            return ''
295        return self.view.url(self.view.context, self.target)
296
297class ClearanceSlipActionButton(ManageActionButton):
298    grok.order(4)
299    grok.context(IStudent)
300    grok.view(StudentClearanceDisplayFormPage)
301    grok.require('waeup.viewStudent')
302    icon = 'actionicon_pdf.png'
[7738]303    text = _('Download clearance slip')
[9452]304    target = 'clearance_slip.pdf'
[7591]305
[8119]306class ClearanceViewActionButton(ManageActionButton):
307    grok.order(1)
308    grok.context(IStudent)
309    grok.view(StudentClearanceEditFormPage)
310    grok.require('waeup.viewStudent')
311    icon = 'actionicon_view.png'
312    text = _('View')
313    target = 'view_clearance'
314
315class PersonalViewActionButton(ManageActionButton):
316    grok.order(1)
317    grok.context(IStudent)
318    grok.view(StudentPersonalEditFormPage)
319    grok.require('waeup.viewStudent')
320    icon = 'actionicon_view.png'
321    text = _('View')
322    target = 'view_personal'
323
[8903]324class StudentPersonalManageActionButton(ManageActionButton):
[7591]325    grok.order(1)
326    grok.context(IStudent)
327    grok.view(StudentPersonalDisplayFormPage)
[8903]328    grok.require('waeup.manageStudent')
329    text = _('Manage')
330    target = 'manage_personal'
331
332class StudentPersonalEditActionButton(ManageActionButton):
333    grok.order(2)
334    grok.context(IStudent)
335    grok.view(StudentPersonalDisplayFormPage)
336    grok.require('waeup.handleStudent')
[7738]337    text = _('Edit')
[7591]338    target = 'edit_personal'
339
340class StudyCourseManageActionButton(ManageActionButton):
341    grok.order(1)
342    grok.context(IStudentStudyCourse)
343    grok.view(StudyCourseDisplayFormPage)
344    grok.require('waeup.manageStudent')
[7738]345    text = _('Manage')
[7591]346    target = 'manage'
347
[9138]348    @property
349    def target_url(self):
350        if self.context.is_current:
351            return self.view.url(self.view.context, self.target)
352        return False
353
[10266]354class StudyCourseTranscriptActionButton(ManageActionButton):
355    grok.order(2)
356    grok.context(IStudentStudyCourse)
357    grok.view(StudyCourseDisplayFormPage)
[10278]358    grok.require('waeup.viewTranscript')
[10266]359    text = _('Transcript')
360    target = 'transcript'
361    icon = 'actionicon_transcript.png'
362
363    @property
364    def target_url(self):
365        if self.context.student.transcript_enabled:
366            return self.view.url(self.view.context, self.target)
367        return False
368
369class TranscriptSlipActionButton(ManageActionButton):
370    grok.order(1)
371    grok.context(IStudentStudyCourse)
372    grok.view(StudyCourseTranscriptPage)
[10278]373    grok.require('waeup.viewTranscript')
[10266]374    text = _('Academic Transcript')
375    target = 'transcript.pdf'
376    icon = 'actionicon_pdf.png'
377
378    @property
379    def target_url(self):
380        if self.context.student.transcript_enabled:
381            return self.view.url(self.view.context, self.target)
382        return False
383
[10060]384class RevertTransferActionButton(ManageActionButton):
385    grok.order(1)
386    grok.context(IStudentStudyCourse)
387    grok.view(StudyCourseDisplayFormPage)
388    grok.require('waeup.manageStudent')
389    icon = 'actionicon_undo.png'
390    text = _('Reactivate this study course (revert previous transfer)')
391    target = 'revert_transfer'
392
393    @property
394    def target_url(self):
395        if self.context.is_previous:
396            return self.view.url(self.view.context.__parent__, self.target)
397        return False
398
[8078]399class StudyLevelManageActionButton(ManageActionButton):
[7591]400    grok.order(1)
401    grok.context(IStudentStudyLevel)
402    grok.view(StudyLevelDisplayFormPage)
403    grok.require('waeup.manageStudent')
[7738]404    text = _('Manage')
[7591]405    target = 'manage'
406
[9138]407    @property
408    def target_url(self):
409        is_current = self.context.__parent__.is_current
410        if not is_current:
411            return ''
412        return self.view.url(self.view.context, self.target)
413
[7591]414class StudentValidateCoursesActionButton(ManageActionButton):
415    grok.order(3)
416    grok.context(IStudentStudyLevel)
417    grok.view(StudyLevelDisplayFormPage)
418    grok.require('waeup.validateStudent')
[7738]419    text = _('Validate courses')
[7591]420    target = 'validate_courses'
421    icon = 'actionicon_accept.png'
422
423    @property
424    def target_url(self):
[9138]425        is_current = self.context.__parent__.is_current
[8736]426        if self.context.student.state != REGISTERED or \
[9138]427            str(self.context.__parent__.current_level) != self.context.__name__ or\
428            not is_current:
[7591]429            return ''
430        return self.view.url(self.view.context, self.target)
431
432class StudentRejectCoursesActionButton(ManageActionButton):
433    grok.order(4)
434    grok.context(IStudentStudyLevel)
435    grok.view(StudyLevelDisplayFormPage)
436    grok.require('waeup.validateStudent')
[7738]437    text = _('Reject courses')
[7591]438    target = 'reject_courses'
439    icon = 'actionicon_reject.png'
440
441    @property
442    def target_url(self):
[9138]443        is_current = self.context.__parent__.is_current
[8736]444        if self.context.student.state not in (VALIDATED, REGISTERED) or \
[9138]445            str(self.context.__parent__.current_level) != self.context.__name__ or\
446            not is_current:
[7591]447            return ''
448        return self.view.url(self.view.context, self.target)
449
[8078]450class CourseRegistrationSlipActionButton(ManageActionButton):
451    grok.order(5)
452    grok.context(IStudentStudyLevel)
453    grok.view(StudyLevelDisplayFormPage)
454    grok.require('waeup.viewStudent')
455    icon = 'actionicon_pdf.png'
456    text = _('Download course registration slip')
[9452]457    target = 'course_registration_slip.pdf'
[8078]458
[9138]459    @property
460    def target_url(self):
461        is_current = self.context.__parent__.is_current
462        if not is_current:
463            return ''
464        return self.view.url(self.view.context, self.target)
465
[7591]466class CourseTicketManageActionButton(ManageActionButton):
467    grok.order(1)
468    grok.context(ICourseTicket)
469    grok.view(CourseTicketDisplayFormPage)
470    grok.require('waeup.manageStudent')
[7738]471    text = _('Manage')
[7591]472    target = 'manage'
473
474#class OnlinePaymentManageActionButton(ManageActionButton):
475#    grok.order(1)
476#    grok.context(IStudentPaymentsContainer)
477#    grok.view(PaymentsDisplayFormPage)
478#    grok.require('waeup.manageStudent')
479#    text = 'Manage payments'
480#    target = 'manage'
481
482class PaymentReceiptActionButton(ManageActionButton):
[9070]483    grok.order(9) # This button should always be the last one.
[7591]484    grok.context(IStudentOnlinePayment)
485    grok.view(OnlinePaymentDisplayFormPage)
486    grok.require('waeup.viewStudent')
487    icon = 'actionicon_pdf.png'
[8262]488    text = _('Download payment slip')
489    target = 'payment_slip.pdf'
[7591]490
491    @property
492    def target_url(self):
[8262]493        #if self.context.p_state != 'paid':
494        #    return ''
[7591]495        return self.view.url(self.view.context, self.target)
496
[8420]497class ApprovePaymentActionButton(ManageActionButton):
[9070]498    grok.order(8)
[7591]499    grok.context(IStudentOnlinePayment)
500    grok.view(OnlinePaymentDisplayFormPage)
[8420]501    grok.require('waeup.managePortal')
[8435]502    icon = 'actionicon_accept.png'
[8420]503    text = _('Approve payment')
504    target = 'approve'
[7591]505
506    @property
507    def target_url(self):
[7888]508        if self.context.p_state == 'paid':
[7591]509            return ''
510        return self.view.url(self.view.context, self.target)
511
512class AddBedTicketActionButton(ManageActionButton):
513    grok.order(1)
514    grok.context(IStudentAccommodation)
515    grok.view(AccommodationManageFormPage)
516    grok.require('waeup.handleAccommodation')
517    icon = 'actionicon_home.png'
[7738]518    text = _('Book accommodation')
[7591]519    target = 'add'
520
521class BedTicketSlipActionButton(ManageActionButton):
522    grok.order(1)
523    grok.context(IBedTicket)
524    grok.view(BedTicketDisplayFormPage)
525    grok.require('waeup.handleAccommodation')
526    icon = 'actionicon_pdf.png'
[7738]527    text = _('Download bed allocation slip')
[9452]528    target = 'bed_allocation_slip.pdf'
[7591]529
530class RelocateStudentActionButton(ManageActionButton):
531    grok.order(2)
532    grok.context(IBedTicket)
533    grok.view(BedTicketDisplayFormPage)
534    grok.require('waeup.manageHostels')
535    icon = 'actionicon_reload.png'
[7738]536    text = _('Relocate student')
[7591]537    target = 'relocate'
538
539class StudentBaseActionButton(ManageActionButton):
540    grok.order(1)
541    grok.context(IStudent)
542    grok.view(StudentBaseDisplayFormPage)
543    grok.require('waeup.handleStudent')
[7876]544    text = _('Edit')
[7591]545    target = 'edit_base'
546
547class StudentPasswordActionButton(ManageActionButton):
548    grok.order(2)
549    grok.context(IStudent)
550    grok.view(StudentBaseDisplayFormPage)
551    grok.require('waeup.handleStudent')
552    icon = 'actionicon_key.png'
[7738]553    text = _('Change password')
[7591]554    target = 'change_password'
555
556class StudentPassportActionButton(ManageActionButton):
557    grok.order(3)
558    grok.context(IStudent)
559    grok.view(StudentBaseDisplayFormPage)
560    grok.require('waeup.handleStudent')
561    icon = 'actionicon_portrait.png'
[7738]562    text = _('Change portrait')
[7591]563    target = 'change_portrait'
564
565    @property
566    def target_url(self):
[10706]567        PWCHANGE_STATES = getUtility(IStudentsUtils).PWCHANGE_STATES
568        if self.context.state not in PWCHANGE_STATES:
[7591]569            return ''
570        return self.view.url(self.view.context, self.target)
571
572class StudentClearanceStartActionButton(ManageActionButton):
573    grok.order(1)
574    grok.context(IStudent)
575    grok.view(StudentClearanceDisplayFormPage)
576    grok.require('waeup.handleStudent')
577    icon = 'actionicon_start.gif'
[7738]578    text = _('Start clearance')
[7591]579    target = 'start_clearance'
580
581    @property
582    def target_url(self):
[7671]583        if self.context.state != ADMITTED:
[7591]584            return ''
585        return self.view.url(self.view.context, self.target)
586
587class StudentClearanceEditActionButton(ManageActionButton):
588    grok.order(1)
589    grok.context(IStudent)
590    grok.view(StudentClearanceDisplayFormPage)
591    grok.require('waeup.handleStudent')
[7738]592    text = _('Edit')
[7591]593    target = 'cedit'
594
595    @property
596    def target_url(self):
597        if self.context.clearance_locked:
598            return ''
599        return self.view.url(self.view.context, self.target)
600
[8476]601class StartSessionActionButton(ManageActionButton):
[7591]602    grok.order(1)
603    grok.context(IStudentStudyCourse)
604    grok.view(StudyCourseDisplayFormPage)
605    grok.require('waeup.handleStudent')
606    icon = 'actionicon_start.gif'
[8920]607    text = _('Start new session')
[8471]608    target = 'start_session'
[7591]609
610    @property
611    def target_url(self):
[9138]612        if self.context.next_session_allowed and self.context.is_current:
[8471]613            return self.view.url(self.view.context, self.target)
614        return False
[7591]615
616class AddStudyLevelActionButton(AddActionButton):
617    grok.order(1)
618    grok.context(IStudentStudyCourse)
619    grok.view(StudyCourseDisplayFormPage)
620    grok.require('waeup.handleStudent')
[7738]621    text = _('Add course list')
[7591]622    target = 'add'
623
624    @property
625    def target_url(self):
[8736]626        student = self.view.context.student
[7671]627        condition1 = student.state != PAID
[7591]628        condition2 = str(student['studycourse'].current_level) in \
629            self.view.context.keys()
[9138]630        condition3 = not self.context.is_current
631        if condition1 or condition2 or condition3:
[7591]632            return ''
633        return self.view.url(self.view.context, self.target)
634
635class StudyLevelEditActionButton(ManageActionButton):
[8078]636    grok.order(2)
[7591]637    grok.context(IStudentStudyLevel)
638    grok.view(StudyLevelDisplayFormPage)
[9924]639    grok.require('waeup.editStudyLevel')
[8920]640    text = _('Edit course list')
[7591]641    target = 'edit'
642
643    @property
644    def target_url(self):
[8736]645        student = self.view.context.student
[9257]646        condition1 = student.state == PAID
647        condition2 = self.view.context.is_current_level
[9138]648        is_current = self.context.__parent__.is_current
[9257]649        if condition1 and condition2 and is_current:
650            return self.view.url(self.view.context, self.target)
651        return ''
[7591]652
[9517]653class AddPaymentActionButton(AddActionButton):
654    grok.order(1)
655    grok.context(IStudentPaymentsContainer)
656    grok.view(PaymentsManageFormPage)
657    grok.require('waeup.payStudent')
658    text = _('Add current session payment ticket')
659    target = 'addop'
660
661class AddPreviousPaymentActionButton(AddActionButton):
662    grok.order(2)
663    grok.context(IStudentPaymentsContainer)
664    grok.view(PaymentsManageFormPage)
665    grok.require('waeup.payStudent')
666    text = _('Add previous session payment ticket')
667    target = 'addpp'
668
669    @property
670    def target_url(self):
671        student = self.view.context.student
[9521]672        if student.before_payment:
[9517]673            return ''
674        return self.view.url(self.view.context, self.target)
675
[9865]676class AddBalancePaymentActionButton(AddActionButton):
677    grok.order(3)
678    grok.context(IStudentPaymentsContainer)
679    grok.view(PaymentsManageFormPage)
[9938]680    grok.require('waeup.manageStudent')
[9865]681    text = _('Add balance payment ticket')
682    target = 'addbp'
683
684    @property
685    def target_url(self):
686        return self.view.url(self.view.context, self.target)
687
[10458]688class RequestTranscriptActionButton(ManageActionButton):
689    grok.order(8)
690    grok.context(IStudent)
691    grok.view(StudentBaseDisplayFormPage)
692    grok.require('waeup.handleStudent')
693    text = _('Request transcript')
694    target = 'request_transcript'
695    icon = 'actionicon_transcript.png'
696
697    @property
698    def target_url(self):
699        if self.context.state != GRADUATED:
700            return ''
701        return self.view.url(self.view.context, self.target)
702
[10459]703class ProcessTranscriptRequestActionButton(ManageActionButton):
[10458]704    grok.order(9)
705    grok.context(IStudent)
706    grok.view(StudentBaseDisplayFormPage)
[10459]707    grok.require('waeup.viewTranscript')
[10458]708    text = _('Manage transcript request')
[10459]709    target = 'process_transcript_request'
[10458]710    icon = 'actionicon_transcript.png'
711
712    @property
713    def target_url(self):
714        if self.context.state != TRANSCRIPT:
715            return ''
716        return self.view.url(self.view.context, self.target)
717
[7184]718class StudentsTab(PrimaryNavTab):
719    """Students tab in primary navigation.
720    """
721
[7819]722    grok.context(IKofaObject)
[7184]723    grok.order(4)
[7240]724    grok.require('waeup.viewStudentsTab')
[10771]725    grok.name('studentstab')
[7184]726
727    pnav = 4
[7674]728    tab_title = _(u'Students')
[7184]729
730    @property
731    def link_target(self):
732        return self.view.application_url('students')
733
[6687]734class PrimaryStudentNavManager(grok.ViewletManager):
735    """Viewlet manager for the primary navigation tab.
736    """
737    grok.name('primary_nav_student')
738
739class PrimaryStudentNavTab(grok.Viewlet):
740    """Base for primary student nav tabs.
741    """
742    grok.baseclass()
743    grok.viewletmanager(PrimaryStudentNavManager)
[7243]744    template = default_primary_nav_template
[6687]745    grok.order(1)
[7184]746    grok.require('waeup.Authenticated')
[8467]747    pnav = 0
[6687]748    tab_title = u'Some Text'
749
750    @property
751    def link_target(self):
752        return self.view.application_url()
753
754    @property
755    def active(self):
756        view_pnav = getattr(self.view, 'pnav', 0)
757        if view_pnav == self.pnav:
758            return 'active'
759        return ''
760
[7240]761class MyStudentDataTab(PrimaryStudentNavTab):
[7459]762    """MyData dropdown tab in primary navigation.
[6687]763    """
764    grok.order(3)
[7240]765    grok.require('waeup.viewMyStudentDataTab')
[7459]766    grok.template('mydatadropdowntabs')
[6687]767    pnav = 4
[7738]768    tab_title = _(u'My Data')
[6687]769
770    @property
[7459]771    def active(self):
772        view_pnav = getattr(self.view, 'pnav', 0)
773        if view_pnav == self.pnav:
774            return 'active dropdown'
775        return 'dropdown'
[7097]776
[7459]777    @property
778    def targets(self):
[9180]779        student = grok.getSite()['students'][self.request.principal.id]
780        student_url = self.view.url(student)
[9178]781        app_slip = getUtility(IExtFileStore).getFileByContext(
[9180]782            student, 'application_slip')
[7459]783        targets = []
[9178]784        if app_slip:
[10805]785            targets = [{'url':student_url + '/application_slip',
786                        'title':_('Application Slip')},]
[7459]787        targets += [
788            {'url':student_url, 'title':'Base Data'},
[8467]789            {'url':student_url + '/view_clearance',
790             'title':_('Clearance Data')},
[7738]791            {'url':student_url + '/view_personal', 'title':_('Personal Data')},
792            {'url':student_url + '/studycourse', 'title':_('Study Course')},
793            {'url':student_url + '/payments', 'title':_('Payments')},
[8467]794            {'url':student_url + '/accommodation',
795             'title':_('Accommodation Data')},
[7738]796            {'url':student_url + '/history', 'title':_('History')},
[7459]797            ]
798        return targets
799
[7107]800def handle_file_delete(context, view, download_name):
801    """Handle deletion of student file.
802
803    """
804    store = getUtility(IExtFileStore)
805    store.deleteFileByContext(context, attr=download_name)
[8735]806    context.writeLogMessage(view, 'deleted: %s' % download_name)
[7738]807    view.flash(_('${a} deleted.', mapping = {'a':download_name}))
[7107]808    return
809
[7106]810def handle_file_upload(upload, context, view, max_size, download_name=None):
811    """Handle upload of student file.
[7097]812
813    Returns `True` in case of success or `False`.
814
815    Please note that file pointer passed in (`upload`) most probably
816    points to end of file when leaving this function.
817    """
[7106]818    # Check some file requirements first
[8467]819    size = file_size(upload)
820    if size > max_size:
821        view.flash(_('Uploaded file is too big.'))
[7106]822        return False
[8467]823    upload.seek(0) # file pointer moved when determining size
824    file_format = get_fileformat(None, upload.read(512))
825    upload.seek(0) # same here
826    if file_format is None:
827        view.flash(_('Could not determine file type.'))
[7106]828        return False
829    basename, expected_ext = os.path.splitext(download_name)
[7123]830    if expected_ext:
[8467]831        if '.' + file_format != expected_ext:
[7738]832            view.flash(_('${a} file extension expected.',
[8467]833                mapping = {'a':expected_ext[1:]}))
[7123]834            return False
835    else:
[8467]836        if not file_format in ALLOWED_FILE_EXTENSIONS:
[7123]837            view.flash(
[8467]838                _('Only the following extensions are allowed: ${a}',
[7738]839                mapping = {'a':', '.join(ALLOWED_FILE_EXTENSIONS)}))
[7123]840            return False
[8467]841        download_name += '.' + file_format
[7097]842    store = getUtility(IExtFileStore)
[7106]843    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
[7097]844    store.createFile(file_id, upload)
[8735]845    context.writeLogMessage(view, 'uploaded: %s (%s)' % (
[8467]846        download_name,upload.filename))
[7738]847    view.flash(_('File ${a} uploaded.', mapping = {'a':download_name}))
[7097]848    return True
849
850class FileManager(grok.ViewletManager):
851    """Viewlet manager for uploading files, preferably scanned images.
852    """
853    grok.name('files')
854
855class FileDisplay(grok.Viewlet):
856    """Base file display viewlet.
857    """
858    grok.baseclass()
[7993]859    grok.context(IStudent)
[7097]860    grok.viewletmanager(FileManager)
861    grok.view(StudentClearanceDisplayFormPage)
[8106]862    template = default_filedisplay_template
[7097]863    grok.order(1)
864    grok.require('waeup.viewStudent')
[7738]865    label = _(u'File')
866    title = _(u'Scan')
[7106]867    download_name = u'filename.jpg'
[7097]868
[7107]869    @property
870    def file_exists(self):
871        image = getUtility(IExtFileStore).getFileByContext(
872            self.context, attr=self.download_name)
873        if image:
874            return True
875        else:
876            return False
877
[7097]878class FileUpload(FileDisplay):
879    """Base upload viewlet.
880    """
881    grok.baseclass()
[7993]882    grok.context(IStudent)
[7097]883    grok.viewletmanager(FileManager)
884    grok.view(StudentClearanceManageFormPage)
[8106]885    template = default_fileupload_template
[7127]886    grok.require('waeup.uploadStudentFile')
[7491]887    tab_redirect = '?tab2'
[7097]888    mus = 1024 * 150
[7735]889    upload_button =_('Upload new file')
890    delete_button = _('Delete attachment')
[7097]891
[7117]892    @property
[10021]893    def show_viewlet(self):
894        students_utils = getUtility(IStudentsUtils)
895        if self.__name__ in students_utils.SKIP_UPLOAD_VIEWLETS:
896            return False
897        return True
898
899    @property
[7117]900    def input_name(self):
901        return "%s" % self.__name__
902
[7097]903    def update(self):
904        self.max_upload_size = string_from_bytes(self.mus)
[7117]905        delete_button = self.request.form.get(
906            'delete_%s' % self.input_name, None)
907        upload_button = self.request.form.get(
908            'upload_%s' % self.input_name, None)
[7108]909        if delete_button:
[7107]910            handle_file_delete(
911                context=self.context, view=self.view,
912                download_name=self.download_name)
913            self.view.redirect(
[7134]914                self.view.url(
915                    self.context, self.view.__name__) + self.tab_redirect)
[7107]916            return
[7108]917        if upload_button:
918            upload = self.request.form.get(self.input_name, None)
919            if upload:
920                # We got a fresh upload
[7111]921                handle_file_upload(upload,
922                    self.context, self.view, self.mus, self.download_name)
923                self.view.redirect(
[7134]924                    self.view.url(
925                        self.context, self.view.__name__) + self.tab_redirect)
[7117]926            else:
[7738]927                self.view.flash(_('No local file selected.'))
[7117]928                self.view.redirect(
[7134]929                    self.view.url(
930                        self.context, self.view.__name__) + self.tab_redirect)
[7097]931        return
932
[7112]933class PassportDisplay(FileDisplay):
934    """Passport display viewlet.
935    """
936    grok.order(1)
937    grok.context(IStudent)
938    grok.view(StudentBaseDisplayFormPage)
939    grok.require('waeup.viewStudent')
940    grok.template('imagedisplay')
[7738]941    label = _(u'Passport Picture')
[7112]942    download_name = u'passport.jpg'
943
944class PassportUploadManage(FileUpload):
945    """Passport upload viewlet for officers.
946    """
947    grok.order(1)
948    grok.context(IStudent)
949    grok.view(StudentBaseManageFormPage)
[7136]950    grok.require('waeup.manageStudent')
[7112]951    grok.template('imageupload')
[7738]952    label = _(u'Passport Picture (jpg only)')
[7112]953    mus = 1024 * 50
954    download_name = u'passport.jpg'
[7491]955    tab_redirect = '?tab2'
[7112]956
957class PassportUploadEdit(PassportUploadManage):
958    """Passport upload viewlet for students.
959    """
[7114]960    grok.view(StudentFilesUploadPage)
[7127]961    grok.require('waeup.uploadStudentFile')
[7112]962
[7097]963class BirthCertificateDisplay(FileDisplay):
[7112]964    """Birth Certificate display viewlet.
[7097]965    """
966    grok.order(1)
[7738]967    label = _(u'Birth Certificate')
968    title = _(u'Birth Certificate Scan')
[7123]969    download_name = u'birth_certificate'
[7097]970
[7280]971class BirthCertificateSlip(BirthCertificateDisplay):
972    grok.view(ExportPDFClearanceSlipPage)
973
[7127]974class BirthCertificateUpload(FileUpload):
[7097]975    """Birth Certificate upload viewlet.
976    """
977    grok.order(1)
[7738]978    label = _(u'Birth Certificate')
979    title = _(u'Birth Certificate Scan')
[7097]980    mus = 1024 * 150
[7123]981    download_name = u'birth_certificate'
[7491]982    tab_redirect = '?tab2'
[7097]983
984class Image(grok.View):
[7351]985    """Renders images for students.
[7097]986    """
[7106]987    grok.baseclass()
[7097]988    grok.name('none.jpg')
[7993]989    grok.context(IStudent)
[7097]990    grok.require('waeup.viewStudent')
[7106]991    download_name = u'none.jpg'
[7097]992
993    def render(self):
994        # A filename chooser turns a context into a filename suitable
995        # for file storage.
996        image = getUtility(IExtFileStore).getFileByContext(
[7106]997            self.context, attr=self.download_name)
[7097]998        if image is None:
999            # show placeholder image
[7123]1000            self.response.setHeader('Content-Type', 'image/jpeg')
[7097]1001            return open(DEFAULT_IMAGE_PATH, 'rb').read()
[7123]1002        dummy,ext = os.path.splitext(image.name)
1003        if ext == '.jpg':
1004            self.response.setHeader('Content-Type', 'image/jpeg')
1005        elif ext == '.png':
1006            self.response.setHeader('Content-Type', 'image/png')
1007        elif ext == '.pdf':
1008            self.response.setHeader('Content-Type', 'application/pdf')
1009        elif ext == '.tif':
1010            self.response.setHeader('Content-Type', 'image/tiff')
[7097]1011        return image
1012
[7112]1013class Passport(Image):
1014    """Renders jpeg passport picture.
1015    """
1016    grok.name('passport.jpg')
1017    download_name = u'passport.jpg'
1018    grok.context(IStudent)
1019
[7351]1020class ApplicationSlipImage(Image):
1021    """Renders application slip scan.
1022    """
1023    grok.name('application_slip')
1024    download_name = u'application_slip'
1025
[7097]1026class BirthCertificateImage(Image):
[7351]1027    """Renders birth certificate scan.
[7097]1028    """
[7123]1029    grok.name('birth_certificate')
1030    download_name = u'birth_certificate'
Note: See TracBrowser for help on using the repository browser.