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

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

Rename permissions and add clearStudent permission.

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