source: main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py @ 6648

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

Show correct title on StudentsContainerManagePage?.

Fix tests (h2 tags removed).

  • Property svn:keywords set to Id
File size: 14.0 KB
Line 
1## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
2## This program is free software; you can redistribute it and/or modify
3## it under the terms of the GNU General Public License as published by
4## the Free Software Foundation; either version 2 of the License, or
5## (at your option) any later version.
6##
7## This program is distributed in the hope that it will be useful,
8## but WITHOUT ANY WARRANTY; without even the implied warranty of
9## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10## GNU General Public License for more details.
11##
12## You should have received a copy of the GNU General Public License
13## along with this program; if not, write to the Free Software
14## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15##
16"""UI components for students and related components.
17"""
18import sys
19import grok
20
21from datetime import datetime
22from zope.formlib.widget import CustomWidgetFactory
23from zope.formlib.form import setUpEditWidgets
24from zope.securitypolicy.interfaces import IPrincipalRoleManager
25from zope.traversing.browser import absoluteURL
26from zope.component import (
27    createObject,)
28
29from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
30from reportlab.pdfgen import canvas
31from reportlab.lib.units import cm
32from reportlab.lib.pagesizes import A4
33from reportlab.lib.styles import getSampleStyleSheet
34from reportlab.platypus import (Frame, Paragraph, Image,
35    Table, Spacer)
36from reportlab.platypus.tables import TableStyle
37
38from waeup.sirp.accesscodes import invalidate_accesscode, get_access_code
39from waeup.sirp.accesscodes.workflow import USED
40from waeup.sirp.browser import (
41    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage, WAeUPDisplayFormPage)
42from waeup.sirp.browser.breadcrumbs import Breadcrumb
43from waeup.sirp.browser.layout import NullValidator
44from waeup.sirp.browser.pages import add_local_role, del_local_roles
45from waeup.sirp.browser.resources import datepicker, tabs, datatable
46from waeup.sirp.browser.viewlets import (
47    ManageActionButton, PrimaryNavTab,
48    AddActionButton, ActionButton, PlainActionButton,
49    )
50from waeup.sirp.image.browser.widget import (
51    ThumbnailWidget, EncodingImageFileWidget,
52    )
53from waeup.sirp.image.image import createWAeUPImageFile
54from waeup.sirp.interfaces import IWAeUPObject, ILocalRolesAssignable
55from waeup.sirp.permissions import get_users_with_local_roles
56from waeup.sirp.university.interfaces import ICertificate
57from waeup.sirp.widgets.datewidget import (
58    FriendlyDateWidget, FriendlyDateDisplayWidget)
59from waeup.sirp.widgets.restwidget import ReSTDisplayWidget
60from waeup.sirp.widgets.objectwidget import (
61    WAeUPObjectWidget, WAeUPObjectDisplayWidget)
62from waeup.sirp.widgets.multilistwidget import (
63    MultiListWidget, MultiListDisplayWidget)
64from waeup.sirp.students.interfaces import (
65    IStudentsContainer, IStudent, IStudentClearance,
66    IStudentPersonal, IStudentBase, IStudentStudyCourse,
67    IStudentPayments, IStudentAccommodation, IStudentNavigation
68    )
69from waeup.sirp.students.student import (
70    Student,
71    )
72from waeup.sirp.students.catalog import search
73
74class StudentsTab(PrimaryNavTab):
75    """Students tab in primary navigation.
76    """
77
78    grok.context(IWAeUPObject)
79    grok.order(3)
80    grok.require('waeup.viewStudents')
81    grok.template('primarynavtab')
82
83    pnav = 4
84    tab_title = u'Students'
85
86    @property
87    def link_target(self):
88        return self.view.application_url('students')
89
90class StudentsBreadcrumb(Breadcrumb):
91    """A breadcrumb for the students container.
92    """
93    grok.context(IStudentsContainer)
94    title = u'Students'
95
96class SudyCourseBreadcrumb(Breadcrumb):
97    """A breadcrumb for the student study course.
98    """
99    grok.context(IStudentStudyCourse)
100    title = u'Study Course'
101
102class PaymentsBreadcrumb(Breadcrumb):
103    """A breadcrumb for the student payments folder.
104    """
105    grok.context(IStudentPayments)
106    title = u'Payments'
107
108class AccommodationBreadcrumb(Breadcrumb):
109    """A breadcrumb for the student accommodation folder.
110    """
111    grok.context(IStudentAccommodation)
112    title = u'Accommodation'
113
114class StudentsContainerPage(WAeUPPage):
115    """The standard view for student containers.
116    """
117    grok.context(IStudentsContainer)
118    grok.name('index')
119    grok.require('waeup.viewStudents')
120    grok.template('studentscontainerpage')
121    pnav = 4
122
123    @property
124    def title(self):
125        return "Students"
126
127    @property
128    def label(self):
129        return self.title
130
131    def update(self, *args, **kw):
132        datatable.need()
133        form = self.request.form
134        self.hitlist = []
135        if 'searchterm' in form and form['searchterm']:
136            self.searchterm = form['searchterm']
137            self.searchtype = form['searchtype']
138        elif 'old_searchterm' in form:
139            self.searchterm = form['old_searchterm']
140            self.searchtype = form['old_searchtype']
141        else:
142            if 'search' in form:
143                self.flash('Empty search string.')
144            return
145        self.hitlist = search(query=self.searchterm,
146            searchtype=self.searchtype, view=self)
147        if not self.hitlist:
148            self.flash('No student found.')
149        return
150
151class StudentsContainerManageActionButton(ManageActionButton):
152    grok.order(1)
153    grok.context(IStudentsContainer)
154    grok.view(StudentsContainerPage)
155    grok.require('waeup.manageStudents')
156    text = 'Manage student section'
157
158
159class StudentsContainerManagePage(WAeUPPage):
160    """The manage page for student containers.
161    """
162    grok.context(IStudentsContainer)
163    grok.name('manage')
164    grok.require('waeup.manageStudents')
165    grok.template('studentscontainermanagepage')
166    pnav = 4
167    title = 'Manage student section'
168
169    @property
170    def label(self):
171        return self.title
172
173    def update(self, *args, **kw):
174        datatable.need()
175        form = self.request.form
176        self.hitlist = []
177        if 'searchterm' in form and form['searchterm']:
178            self.searchterm = form['searchterm']
179            self.searchtype = form['searchtype']
180        elif 'old_searchterm' in form:
181            self.searchterm = form['old_searchterm']
182            self.searchtype = form['old_searchtype']
183        else:
184            if 'search' in form:
185                self.flash('Empty search string.')
186            return
187        #import pdb; pdb.set_trace()
188        if not 'entries' in form:
189            self.hitlist = search(query=self.searchterm,
190                searchtype=self.searchtype, view=self)
191            if not self.hitlist:
192                self.flash('No student found.')
193            return
194        entries = form['entries']
195        if isinstance(entries, basestring):
196            entries = [entries]
197        deleted = []
198        for entry in entries:
199            if 'remove' in form:
200                del self.context[entry]
201                deleted.append(entry)
202        self.hitlist = search(query=self.searchterm,
203            searchtype=self.searchtype, view=self)
204        if len(deleted):
205            self.flash('Successfully removed: %s' % ', '.join(deleted))
206        return
207
208class StudentsContainerAddActionButton(AddActionButton):
209    grok.order(1)
210    grok.context(IStudentsContainer)
211    grok.view(StudentsContainerManagePage)
212    grok.require('waeup.manageStudents')
213    text = 'Add student'
214    target = 'addstudent'
215
216class StudentAddFormPage(WAeUPAddFormPage):
217    """Add-form to add a student.
218    """
219    grok.context(IStudentsContainer)
220    grok.require('waeup.manageStudents')
221    grok.name('addstudent')
222    grok.template('studentaddpage')
223    form_fields = grok.AutoFields(IStudent)
224    title = 'Students'
225    label = 'Add student'
226    pnav = 4
227
228    @grok.action('Create student record')
229    def addStudent(self, **data):
230        student_id = self.request.form.get('form.student_id')
231        student = createObject(u'waeup.Student')
232        student.student_id = student_id
233        self.applyData(student, **data)
234        #import pdb; pdb.set_trace()
235        try:
236            self.context.addStudent(student)
237        except KeyError:
238            self.flash('The student id chosen already exists.')
239            return
240        self.flash('Student record created.')
241        self.redirect(self.url(self.context[student_id], 'index'))
242        return
243
244class StudentBaseDisplayFormPage(WAeUPDisplayFormPage):
245    """ Page to display student base data
246    """
247    grok.context(IStudent)
248    grok.name('index')
249    grok.require('waeup.viewStudents')
250    grok.template('studentpage')
251    form_fields = grok.AutoFields(IStudentBase)
252    pnav = 4
253    title = 'Base Data'
254
255    @property
256    def label(self):
257        return '%s: Base Data' % self.context.name
258
259class StudentBaseManageActionButton(ManageActionButton):
260    grok.order(1)
261    grok.context(IStudent)
262    grok.view(StudentBaseDisplayFormPage)
263    grok.require('waeup.manageStudents')
264    text = 'Edit'
265    target = 'edit_base'
266
267class StudentBaseManageFormPage(WAeUPEditFormPage):
268    """ View to edit student base data
269    """
270    grok.context(IStudent)
271    grok.name('edit_base')
272    grok.require('waeup.manageStudents')
273    form_fields = grok.AutoFields(IStudentBase).omit('student_id')
274    grok.template('studentbasemanagepage')
275    label = 'Edit base data'
276    title = 'Base Data'
277    pnav = 4
278
279    def update(self):
280        datepicker.need() # Enable jQuery datepicker in date fields.
281        super(StudentBaseManageFormPage, self).update()
282        self.wf_info = IWorkflowInfo(self.context)
283        return
284
285    def getTransitions(self):
286        """Return a list of dicts of allowed transition ids and titles.
287
288        Each list entry provides keys ``name`` and ``title`` for
289        internal name and (human readable) title of a single
290        transition.
291        """
292        allowed_transitions = self.wf_info.getManualTransitions()
293        return [dict(name='', title='No transition')] +[
294            dict(name=x, title=y) for x, y in allowed_transitions]
295
296    @grok.action('Save')
297    def save(self, **data):
298        changed_fields = self.applyData(self.context, **data)
299        changed_fields = changed_fields.values()
300        fields_string = '+'.join(' + '.join(str(i) for i in b) for b in changed_fields)
301        self.context._p_changed = True
302        form = self.request.form
303        if form.has_key('transition') and form['transition']:
304            transition_id = form['transition']
305            self.wf_info.fireTransition(transition_id)
306        self.flash('Form has been saved.')
307        ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
308        if fields_string:
309            self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
310        return
311
312class StudentClearanceDisplayFormPage(WAeUPDisplayFormPage):
313    """ Page to display student clearance data
314    """
315    grok.context(IStudent)
316    grok.name('view_clearance')
317    grok.require('waeup.viewStudents')
318    form_fields = grok.AutoFields(IStudentClearance)
319    title = 'Clearance Data'
320    pnav = 4
321
322    @property
323    def label(self):
324        return '%s: Clearance Data' % self.context.name
325
326class StudentClearanceManageActionButton(ManageActionButton):
327    grok.order(1)
328    grok.context(IStudent)
329    grok.view(StudentClearanceDisplayFormPage)
330    grok.require('waeup.manageStudents')
331    text = 'Edit'
332    target = 'edit_clearance'
333
334class StudentClearanceManageFormPage(WAeUPEditFormPage):
335    """ Page to edit student clearance data
336    """
337    grok.context(IStudent)
338    grok.name('edit_clearance')
339    grok.require('waeup.viewStudents')
340    form_fields = grok.AutoFields(IStudentClearance)
341    label = 'Edit clearance data'
342    title = 'Clearance Data'
343    pnav = 4
344
345class StudentPersonalDisplayFormPage(WAeUPDisplayFormPage):
346    """ Page to display student personal data
347    """
348    grok.context(IStudent)
349    grok.name('view_personal')
350    grok.require('waeup.viewStudents')
351    form_fields = grok.AutoFields(IStudentPersonal)
352    title = 'Personal Data'
353    pnav = 4
354
355    @property
356    def label(self):
357        return '%s: Personal Data' % self.context.name
358
359class StudentPersonalManageActionButton(ManageActionButton):
360    grok.order(1)
361    grok.context(IStudent)
362    grok.view(StudentPersonalDisplayFormPage)
363    grok.require('waeup.manageStudents')
364    text = 'Edit'
365    target = 'edit_personal'
366
367class StudentPersonalManageFormPage(WAeUPEditFormPage):
368    """ Page to edit student clearance data
369    """
370    grok.context(IStudent)
371    grok.name('edit_personal')
372    grok.require('waeup.viewStudents')
373    form_fields = grok.AutoFields(IStudentPersonal)
374    label = 'Edit personal data'
375    title = 'Personal Data'
376    pnav = 4
377
378class StudyCourseDisplayFormPage(WAeUPDisplayFormPage):
379    """ Page to display the student study course data
380    """
381    grok.context(IStudentStudyCourse)
382    grok.name('index')
383    grok.require('waeup.viewStudents')
384    form_fields = grok.AutoFields(IStudentStudyCourse)
385    #grok.template('studycoursepage')
386    title = 'Study Course'
387    pnav = 4
388
389    @property
390    def label(self):
391        return '%s: Study Course' % self.context.__parent__.name
392
393class PaymentsDisplayFormPage(WAeUPDisplayFormPage):
394    """ Page to display the student payments
395    """
396    grok.context(IStudentPayments)
397    grok.name('index')
398    grok.require('waeup.viewStudents')
399    form_fields = grok.AutoFields(IStudentPayments)
400    #grok.template('paymentspage')
401    title = 'Payments'
402    pnav = 4
403
404    @property
405    def label(self):
406        return '%s: Payments' % self.context.__parent__.name
407
408class AccommodationDisplayFormPage(WAeUPDisplayFormPage):
409    """ Page to display the student accommodation data
410    """
411    grok.context(IStudentAccommodation)
412    grok.name('index')
413    grok.require('waeup.viewStudents')
414    form_fields = grok.AutoFields(IStudentAccommodation)
415    #grok.template('accommodationpage')
416    title = 'Accommodation'
417    pnav = 4
418
419    @property
420    def label(self):
421        return '%s: Accommodation Data' % self.context.__parent__.name
422
423class StudentHistoryPage(WAeUPPage):
424    """ Page to display student clearance data
425    """
426    grok.context(IStudent)
427    grok.name('history')
428    grok.require('waeup.viewStudents')
429    grok.template('studenthistory')
430    title = 'History'
431    pnav = 4
432
433    @property
434    def label(self):
435        return '%s: History' % self.context.name
Note: See TracBrowser for help on using the repository browser.