source: main/waeup.sirp/trunk/src/waeup/sirp/students/viewlets.py @ 7122

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

Add upload pages for students.

input_name should correspond with the name of the view otherwise zope.manager will get problems when uploading a file because zope.manager does see both viewlets.

  • Property svn:keywords set to Id
File size: 11.9 KB
RevLine 
[7106]1import os
[6642]2import grok
[7097]3from zope.component import getUtility
[6642]4from zope.interface import Interface
[7097]5from waeup.sirp.interfaces import (
6    IWAeUPObject, IExtFileStore, IFileStoreNameChooser)
7from waeup.sirp.utils.helpers import string_from_bytes, file_size
8from waeup.sirp.browser import DEFAULT_IMAGE_PATH
9from waeup.sirp.students.browser import (
[7108]10    StudentClearanceDisplayFormPage, StudentClearanceManageFormPage,
[7112]11    write_log_message, StudentBaseManageFormPage, StudentBaseDisplayFormPage,
[7114]12    StudentFilesUploadPage)
[7112]13from waeup.sirp.students.interfaces import IStudent, IStudentClearance
[6642]14
15grok.context(IWAeUPObject) # Make IWAeUPObject the default context
[6687]16grok.templatedir('browser_templates')
[6642]17
[6687]18class StudentManageSidebar(grok.ViewletManager):
19    grok.name('left_studentmanage')
[6642]20
[6687]21class StudentManageLink(grok.Viewlet):
[6660]22    """A link displayed in the student box which shows up for StudentNavigation
[6642]23    objects.
24
25    """
26    grok.baseclass()
[6687]27    grok.viewletmanager(StudentManageSidebar)
[6642]28    grok.context(IWAeUPObject)
29    grok.view(Interface)
30    grok.order(5)
[6660]31    grok.require('waeup.viewStudent')
[6642]32
33    link = 'index'
34    text = u'Base Data'
35
36    def render(self):
37        url = self.view.url(self.context.getStudent(), self.link)
38        return u'<div class="portlet"><a href="%s">%s</a></div>' % (
39                url, self.text)
40
[6687]41class StudentManageBaseLink(StudentManageLink):
42    grok.order(1)
43    link = 'index'
44    text = u'Base Data'
45
46class StudentManageClearanceLink(StudentManageLink):
47    grok.order(2)
48    link = 'view_clearance'
49    text = u'Clearance Data'
50
51class StudentManagePersonalLink(StudentManageLink):
52    grok.order(2)
53    link = 'view_personal'
54    text = u'Personal Data'
55
56class StudentManageStudyCourseLink(StudentManageLink):
57    grok.order(3)
58    link = 'studycourse'
59    text = u'Study Course'
60
61class StudentManagePaymentsLink(StudentManageLink):
62    grok.order(4)
63    link = 'payments'
64    text = u'Payments'
65
66class StudentManageAccommodationLink(StudentManageLink):
67    grok.order(5)
68    link = 'accommodation'
69    text = u'Accommodation Data'
70
71class StudentManageHistoryLink(StudentManageLink):
72    grok.order(6)
73    link = 'history'
74    text = u'History'
75
76
77class StudentMenu(grok.ViewletManager):
78    grok.name('top_student')
79
80class StudentLink(grok.Viewlet):
81    """A link displayed in the student box which shows up for StudentNavigation
82    objects.
83
84    """
85    grok.baseclass()
86    grok.viewletmanager(StudentMenu)
87    grok.context(IWAeUPObject)
88    grok.view(Interface)
89    grok.order(5)
90    grok.require('waeup.viewStudent')
91    template = grok.PageTemplateFile('browser_templates/plainactionbutton.pt')
92
93    link = 'index'
94    text = u'Base Data'
95
96    @property
97    def target_url(self):
98        """Get a URL to the target...
99        """
100        return self.view.url(self.context.getStudent(), self.link)
101
[6642]102class StudentBaseLink(StudentLink):
103    grok.order(1)
104    link = 'index'
105    text = u'Base Data'
106
107class StudentClearanceLink(StudentLink):
108    grok.order(2)
109    link = 'view_clearance'
110    text = u'Clearance Data'
111
112class StudentPersonalLink(StudentLink):
113    grok.order(2)
114    link = 'view_personal'
115    text = u'Personal Data'
116
117class StudentStudyCourseLink(StudentLink):
118    grok.order(3)
119    link = 'studycourse'
120    text = u'Study Course'
121
122class StudentPaymentsLink(StudentLink):
123    grok.order(4)
124    link = 'payments'
125    text = u'Payments'
126
127class StudentAccommodationLink(StudentLink):
128    grok.order(5)
129    link = 'accommodation'
[6687]130    text = u'Accommodation'
[6642]131
132class StudentHistoryLink(StudentLink):
133    grok.order(6)
134    link = 'history'
135    text = u'History'
[6687]136
137class PrimaryStudentNavManager(grok.ViewletManager):
138    """Viewlet manager for the primary navigation tab.
139    """
140    grok.name('primary_nav_student')
141
142class PrimaryStudentNavTab(grok.Viewlet):
143    """Base for primary student nav tabs.
144    """
145    grok.baseclass()
146    grok.viewletmanager(PrimaryStudentNavManager)
147    grok.template('primarynavtab')
148    grok.order(1)
149    grok.require('waeup.View')
150    pnav = 0
151    tab_title = u'Some Text'
152
153    @property
154    def link_target(self):
155        return self.view.application_url()
156
157    @property
158    def active(self):
159        view_pnav = getattr(self.view, 'pnav', 0)
160        if view_pnav == self.pnav:
161            return 'active'
162        return ''
163
164class HomeTab(PrimaryStudentNavTab):
165    """Home-tab in primary navigation.
166    """
167    grok.order(1)
168    grok.require('waeup.Public')
169    pnav = 0
170    tab_title = u'Home'
171
172class ProspectusTab(PrimaryStudentNavTab):
173    """Faculties-tab in primary navigation.
174    """
175    grok.order(2)
176    grok.require('waeup.View')
177    pnav = 1
178    tab_title = u'Prospectus'
179
180    @property
181    def link_target(self):
182        return self.view.application_url('faculties')
183
184class MyDataTab(PrimaryStudentNavTab):
185    """MyData-tab in primary navigation.
186    """
187    grok.order(3)
188    grok.require('waeup.Public')
189    pnav = 4
190    tab_title = u'My Data'
191
192    @property
193    def link_target(self):
194        rel_link = '/students/%s' % self.request.principal.id
[7097]195        return self.view.application_url() + rel_link
196
[7107]197def handle_file_delete(context, view, download_name):
198    """Handle deletion of student file.
199
200    """
201    store = getUtility(IExtFileStore)
202    store.deleteFileByContext(context, attr=download_name)
[7108]203    write_log_message(view, 'deleted: %s' % download_name)
[7107]204    view.flash('File %s deleted.' % download_name)
205    return
206
[7106]207def handle_file_upload(upload, context, view, max_size, download_name=None):
208    """Handle upload of student file.
[7097]209
210    Returns `True` in case of success or `False`.
211
212    Please note that file pointer passed in (`upload`) most probably
213    points to end of file when leaving this function.
214    """
[7106]215    # Check some file requirements first
216    if upload.filename.count('.') == 0:
217        view.flash('File name has no extension.')
218        return False
219    if upload.filename.count('.') > 1:
220        view.flash('File name contains more than one dot.')
221        return False
222    basename, expected_ext = os.path.splitext(download_name)
223    dummy, ext = os.path.splitext(upload.filename)
224    ext.lower()
225    if ext != expected_ext:
[7108]226        view.flash('%s file extension expected.' % expected_ext)
[7106]227        return False
[7097]228    size = file_size(upload)
229    if size > max_size:
[7106]230        view.flash('Uploaded file is too big.')
[7097]231        return False
232    upload.seek(0) # file pointer moved when determining size
233    store = getUtility(IExtFileStore)
[7106]234    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
[7097]235    store.createFile(file_id, upload)
[7108]236    write_log_message(view, 'uploaded: %s (%s)' % (download_name,upload.filename))
237    view.flash('File %s uploaded.' % download_name)
[7097]238    return True
239
240class FileManager(grok.ViewletManager):
241    """Viewlet manager for uploading files, preferably scanned images.
242    """
243    grok.name('files')
244
245class FileDisplay(grok.Viewlet):
246    """Base file display viewlet.
247    """
248    grok.baseclass()
[7100]249    grok.context(IStudentClearance)
[7097]250    grok.viewletmanager(FileManager)
251    grok.view(StudentClearanceDisplayFormPage)
252    grok.template('filedisplay')
253    grok.order(1)
254    grok.require('waeup.viewStudent')
[7106]255    label = u'File:'
256    download_name = u'filename.jpg'
[7097]257
[7107]258    @property
259    def file_exists(self):
260        image = getUtility(IExtFileStore).getFileByContext(
261            self.context, attr=self.download_name)
262        if image:
263            return True
264        else:
265            return False
266
[7097]267class FileUpload(FileDisplay):
268    """Base upload viewlet.
269    """
270    grok.baseclass()
[7100]271    grok.context(IStudentClearance)
[7097]272    grok.viewletmanager(FileManager)
273    grok.view(StudentClearanceManageFormPage)
274    grok.template('fileupload')
275    grok.require('waeup.manageStudents')
276    mus = 1024 * 150
277
[7117]278    @property
279    def input_name(self):
280        return "%s" % self.__name__
281
[7097]282    def update(self):
283        self.max_upload_size = string_from_bytes(self.mus)
[7117]284        delete_button = self.request.form.get(
285            'delete_%s' % self.input_name, None)
286        upload_button = self.request.form.get(
287            'upload_%s' % self.input_name, None)
[7108]288        if delete_button:
[7107]289            handle_file_delete(
290                context=self.context, view=self.view,
291                download_name=self.download_name)
292            self.view.redirect(
293                self.view.url(self.context, self.view.__name__))
294            return
[7108]295        if upload_button:
296            upload = self.request.form.get(self.input_name, None)
297            if upload:
298                # We got a fresh upload
[7111]299                handle_file_upload(upload,
300                    self.context, self.view, self.mus, self.download_name)
301                self.view.redirect(
302                    self.view.url(self.context, self.view.__name__))
[7117]303            else:
304                self.view.flash('No local file selected.')
305                self.view.redirect(
306                    self.view.url(self.context, self.view.__name__))
[7097]307        return
308
[7112]309class PassportDisplay(FileDisplay):
310    """Passport display viewlet.
311    """
312    grok.order(1)
313    grok.context(IStudent)
314    grok.view(StudentBaseDisplayFormPage)
315    grok.require('waeup.viewStudent')
316    grok.template('imagedisplay')
317    label = u'Passport Picture:'
318    download_name = u'passport.jpg'
319
320class PassportUploadManage(FileUpload):
321    """Passport upload viewlet for officers.
322    """
323    grok.order(1)
324    grok.context(IStudent)
325    grok.view(StudentBaseManageFormPage)
326    grok.require('waeup.manageStudents')
327    grok.template('imageupload')
328    label = u'Passport Picture (jpg only):'
329    mus = 1024 * 50
330    download_name = u'passport.jpg'
331
332class PassportUploadEdit(PassportUploadManage):
333    """Passport upload viewlet for students.
334    """
[7114]335    grok.view(StudentFilesUploadPage)
[7112]336    grok.require('waeup.handleStudent')
337
[7097]338class BirthCertificateDisplay(FileDisplay):
[7112]339    """Birth Certificate display viewlet.
[7097]340    """
341    grok.order(1)
342    label = u'Birth Certificate:'
[7106]343    download_name = u'birth_certificate.jpg'
[7097]344
[7117]345class BirthCertificateUploadManage(FileUpload):
[7097]346    """Birth Certificate upload viewlet.
347    """
348    grok.order(1)
[7108]349    label = u'Birth Certificate (jpg only):'
[7097]350    mus = 1024 * 150
[7106]351    download_name = u'birth_certificate.jpg'
[7097]352
[7111]353class AcceptanceLetterDisplay(FileDisplay):
[7112]354    """Acceptance Letter display viewlet.
[7111]355    """
356    grok.order(1)
357    label = u'Acceptance Letter:'
358    download_name = u'acceptance_letter.jpg'
359
[7117]360class AcceptanceLetterUploadManage(FileUpload):
[7111]361    """AcceptanceLetter upload viewlet.
362    """
[7112]363    grok.order(2)
[7111]364    label = u'Acceptance Letter (jpg only):'
365    mus = 1024 * 150
366    download_name = u'acceptance_letter.jpg'
367
[7117]368class BirthCertificateUploadEdit(BirthCertificateUploadManage):
369    """Birth Certificate upload viewlet for student.
370    """
371    grok.require('waeup.handleStudent')
372
373class AcceptanceLetterUploadEdit(AcceptanceLetterUploadManage):
374    """AcceptanceLetter upload viewlet for student.
375    """
376    grok.require('waeup.handleStudent')
377
[7097]378class Image(grok.View):
[7106]379    """Renders jpeg images for students.
[7097]380    """
[7106]381    grok.baseclass()
[7097]382    grok.name('none.jpg')
[7112]383    grok.context(IStudentClearance)
[7097]384    grok.require('waeup.viewStudent')
[7106]385    download_name = u'none.jpg'
[7097]386
387    def render(self):
388        # A filename chooser turns a context into a filename suitable
389        # for file storage.
390        image = getUtility(IExtFileStore).getFileByContext(
[7106]391            self.context, attr=self.download_name)
392        # We expect that image is a jpeg pictures
[7097]393        self.response.setHeader(
394            'Content-Type', 'image/jpeg')
395        if image is None:
396            # show placeholder image
397            return open(DEFAULT_IMAGE_PATH, 'rb').read()
398        return image
399
[7112]400class Passport(Image):
401    """Renders jpeg passport picture.
402    """
403    grok.name('passport.jpg')
404    download_name = u'passport.jpg'
405    grok.context(IStudent)
406
[7097]407class BirthCertificateImage(Image):
[7111]408    """Renders birth certificate jpeg scan.
[7097]409    """
410    grok.name('birth_certificate.jpg')
[7111]411    download_name = u'birth_certificate.jpg'
412
413class AcceptanceLetterImage(Image):
414    """Renders acceptance letter jpeg scan.
415    """
416    grok.name('acceptance_letter.jpg')
417    download_name = u'acceptance_letter.jpg'
Note: See TracBrowser for help on using the repository browser.