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
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
18class StudentManageSidebar(grok.ViewletManager):
19    grok.name('left_studentmanage')
20
21class StudentManageLink(grok.Viewlet):
22    """A link displayed in the student box which shows up for StudentNavigation
23    objects.
24
25    """
26    grok.baseclass()
27    grok.viewletmanager(StudentManageSidebar)
28    grok.context(IWAeUPObject)
29    grok.view(Interface)
30    grok.order(5)
31    grok.require('waeup.viewStudent')
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
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
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'
130    text = u'Accommodation'
131
132class StudentHistoryLink(StudentLink):
133    grok.order(6)
134    link = 'history'
135    text = u'History'
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
195        return self.view.application_url() + rel_link
196
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)
203    write_log_message(view, 'deleted: %s' % download_name)
204    view.flash('File %s deleted.' % download_name)
205    return
206
207def handle_file_upload(upload, context, view, max_size, download_name=None):
208    """Handle upload of student file.
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    """
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:
226        view.flash('%s file extension expected.' % expected_ext)
227        return False
228    size = file_size(upload)
229    if size > max_size:
230        view.flash('Uploaded file is too big.')
231        return False
232    upload.seek(0) # file pointer moved when determining size
233    store = getUtility(IExtFileStore)
234    file_id = IFileStoreNameChooser(context).chooseName(attr=download_name)
235    store.createFile(file_id, upload)
236    write_log_message(view, 'uploaded: %s (%s)' % (download_name,upload.filename))
237    view.flash('File %s uploaded.' % download_name)
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()
249    grok.context(IStudentClearance)
250    grok.viewletmanager(FileManager)
251    grok.view(StudentClearanceDisplayFormPage)
252    grok.template('filedisplay')
253    grok.order(1)
254    grok.require('waeup.viewStudent')
255    label = u'File:'
256    download_name = u'filename.jpg'
257
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
267class FileUpload(FileDisplay):
268    """Base upload viewlet.
269    """
270    grok.baseclass()
271    grok.context(IStudentClearance)
272    grok.viewletmanager(FileManager)
273    grok.view(StudentClearanceManageFormPage)
274    grok.template('fileupload')
275    grok.require('waeup.manageStudents')
276    mus = 1024 * 150
277
278    @property
279    def input_name(self):
280        return "%s" % self.__name__
281
282    def update(self):
283        self.max_upload_size = string_from_bytes(self.mus)
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)
288        if delete_button:
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
295        if upload_button:
296            upload = self.request.form.get(self.input_name, None)
297            if upload:
298                # We got a fresh upload
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__))
303            else:
304                self.view.flash('No local file selected.')
305                self.view.redirect(
306                    self.view.url(self.context, self.view.__name__))
307        return
308
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    """
335    grok.view(StudentFilesUploadPage)
336    grok.require('waeup.handleStudent')
337
338class BirthCertificateDisplay(FileDisplay):
339    """Birth Certificate display viewlet.
340    """
341    grok.order(1)
342    label = u'Birth Certificate:'
343    download_name = u'birth_certificate.jpg'
344
345class BirthCertificateUploadManage(FileUpload):
346    """Birth Certificate upload viewlet.
347    """
348    grok.order(1)
349    label = u'Birth Certificate (jpg only):'
350    mus = 1024 * 150
351    download_name = u'birth_certificate.jpg'
352
353class AcceptanceLetterDisplay(FileDisplay):
354    """Acceptance Letter display viewlet.
355    """
356    grok.order(1)
357    label = u'Acceptance Letter:'
358    download_name = u'acceptance_letter.jpg'
359
360class AcceptanceLetterUploadManage(FileUpload):
361    """AcceptanceLetter upload viewlet.
362    """
363    grok.order(2)
364    label = u'Acceptance Letter (jpg only):'
365    mus = 1024 * 150
366    download_name = u'acceptance_letter.jpg'
367
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
378class Image(grok.View):
379    """Renders jpeg images for students.
380    """
381    grok.baseclass()
382    grok.name('none.jpg')
383    grok.context(IStudentClearance)
384    grok.require('waeup.viewStudent')
385    download_name = u'none.jpg'
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(
391            self.context, attr=self.download_name)
392        # We expect that image is a jpeg pictures
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
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
407class BirthCertificateImage(Image):
408    """Renders birth certificate jpeg scan.
409    """
410    grok.name('birth_certificate.jpg')
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.