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

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

Add tests (test coverage of viewlets.py now 100%).

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