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

Last change on this file since 7113 was 7112, checked in by Henrik Bettermann, 14 years ago

Add passport picture uploader to student base data pages.

  • Property svn:keywords set to Id
File size: 11.5 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    StudentBaseEditFormPage)
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    input_name = u'filename'
278
279    def update(self):
280        self.max_upload_size = string_from_bytes(self.mus)
281        delete_button = self.request.form.get('delete_%s' % self.input_name, None)
282        upload_button = self.request.form.get('upload_%s' % self.input_name, None)
283        if delete_button:
284            handle_file_delete(
285                context=self.context, view=self.view,
286                download_name=self.download_name)
287            self.view.redirect(
288                self.view.url(self.context, self.view.__name__))
289            return
290        if upload_button:
291            upload = self.request.form.get(self.input_name, None)
292            if upload:
293                # We got a fresh upload
294                handle_file_upload(upload,
295                    self.context, self.view, self.mus, self.download_name)
296                self.view.redirect(
297                    self.view.url(self.context, self.view.__name__))
298        return
299
300class PassportDisplay(FileDisplay):
301    """Passport display viewlet.
302    """
303    grok.order(1)
304    grok.context(IStudent)
305    grok.view(StudentBaseDisplayFormPage)
306    grok.require('waeup.viewStudent')
307    grok.template('imagedisplay')
308    label = u'Passport Picture:'
309    download_name = u'passport.jpg'
310
311class PassportUploadManage(FileUpload):
312    """Passport upload viewlet for officers.
313    """
314    grok.order(1)
315    grok.context(IStudent)
316    grok.view(StudentBaseManageFormPage)
317    grok.require('waeup.manageStudents')
318    grok.template('imageupload')
319    label = u'Passport Picture (jpg only):'
320    mus = 1024 * 50
321    download_name = u'passport.jpg'
322    input_name = u'passport'
323
324class PassportUploadEdit(PassportUploadManage):
325    """Passport upload viewlet for students.
326    """
327    grok.view(StudentBaseEditFormPage)
328    grok.require('waeup.handleStudent')
329
330class BirthCertificateDisplay(FileDisplay):
331    """Birth Certificate display viewlet.
332    """
333    grok.order(1)
334    label = u'Birth Certificate:'
335    download_name = u'birth_certificate.jpg'
336
337class BirthCertificateUpload(FileUpload):
338    """Birth Certificate upload viewlet.
339    """
340    grok.order(1)
341    label = u'Birth Certificate (jpg only):'
342    mus = 1024 * 150
343    download_name = u'birth_certificate.jpg'
344    input_name = u'birth_certificate'
345
346class AcceptanceLetterDisplay(FileDisplay):
347    """Acceptance Letter display viewlet.
348    """
349    grok.order(1)
350    label = u'Acceptance Letter:'
351    download_name = u'acceptance_letter.jpg'
352
353class AcceptanceLetterUpload(FileUpload):
354    """AcceptanceLetter upload viewlet.
355    """
356    grok.order(2)
357    label = u'Acceptance Letter (jpg only):'
358    mus = 1024 * 150
359    download_name = u'acceptance_letter.jpg'
360    input_name = u'acceptance_letter'
361
362class Image(grok.View):
363    """Renders jpeg images for students.
364    """
365    grok.baseclass()
366    grok.name('none.jpg')
367    grok.context(IStudentClearance)
368    grok.require('waeup.viewStudent')
369    download_name = u'none.jpg'
370
371    def render(self):
372        # A filename chooser turns a context into a filename suitable
373        # for file storage.
374        image = getUtility(IExtFileStore).getFileByContext(
375            self.context, attr=self.download_name)
376        # We expect that image is a jpeg pictures
377        self.response.setHeader(
378            'Content-Type', 'image/jpeg')
379        if image is None:
380            # show placeholder image
381            return open(DEFAULT_IMAGE_PATH, 'rb').read()
382        return image
383
384class Passport(Image):
385    """Renders jpeg passport picture.
386    """
387    grok.name('passport.jpg')
388    download_name = u'passport.jpg'
389    grok.context(IStudent)
390
391class BirthCertificateImage(Image):
392    """Renders birth certificate jpeg scan.
393    """
394    grok.name('birth_certificate.jpg')
395    download_name = u'birth_certificate.jpg'
396
397class AcceptanceLetterImage(Image):
398    """Renders acceptance letter jpeg scan.
399    """
400    grok.name('acceptance_letter.jpg')
401    download_name = u'acceptance_letter.jpg'
Note: See TracBrowser for help on using the repository browser.