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

Last change on this file since 7112 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
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,
12    StudentBaseEditFormPage)
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
[7108]277    input_name = u'filename'
[7097]278
279    def update(self):
280        self.max_upload_size = string_from_bytes(self.mus)
[7111]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)
[7108]283        if delete_button:
[7107]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
[7108]290        if upload_button:
291            upload = self.request.form.get(self.input_name, None)
292            if upload:
293                # We got a fresh upload
[7111]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__))
[7097]298        return
299
[7112]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
[7097]330class BirthCertificateDisplay(FileDisplay):
[7112]331    """Birth Certificate display viewlet.
[7097]332    """
333    grok.order(1)
334    label = u'Birth Certificate:'
[7106]335    download_name = u'birth_certificate.jpg'
[7097]336
337class BirthCertificateUpload(FileUpload):
338    """Birth Certificate upload viewlet.
339    """
340    grok.order(1)
[7108]341    label = u'Birth Certificate (jpg only):'
[7097]342    mus = 1024 * 150
[7106]343    download_name = u'birth_certificate.jpg'
[7108]344    input_name = u'birth_certificate'
[7097]345
[7111]346class AcceptanceLetterDisplay(FileDisplay):
[7112]347    """Acceptance Letter display viewlet.
[7111]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    """
[7112]356    grok.order(2)
[7111]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
[7097]362class Image(grok.View):
[7106]363    """Renders jpeg images for students.
[7097]364    """
[7106]365    grok.baseclass()
[7097]366    grok.name('none.jpg')
[7112]367    grok.context(IStudentClearance)
[7097]368    grok.require('waeup.viewStudent')
[7106]369    download_name = u'none.jpg'
[7097]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(
[7106]375            self.context, attr=self.download_name)
376        # We expect that image is a jpeg pictures
[7097]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
[7112]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
[7097]391class BirthCertificateImage(Image):
[7111]392    """Renders birth certificate jpeg scan.
[7097]393    """
394    grok.name('birth_certificate.jpg')
[7111]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.