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

Last change on this file since 6675 was 6675, checked in by uli, 13 years ago

Remove imports of multilist stuff.

  • Property svn:keywords set to Id
File size: 14.5 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.students.interfaces import (
63    IStudentsContainer, IStudent, IStudentClearance,
64    IStudentPersonal, IStudentBase, IStudentStudyCourse,
65    IStudentPayments, IStudentAccommodation, IStudentNavigation
66    )
67from waeup.sirp.students.student import Student
68from waeup.sirp.students.catalog import search
69
70class StudentsTab(PrimaryNavTab):
71    """Students tab in primary navigation.
72    """
73
74    grok.context(IWAeUPObject)
75    grok.order(3)
76    grok.require('waeup.viewStudent')
77    grok.template('primarynavtab')
78
79    pnav = 4
80    tab_title = u'Students'
81
82    @property
83    def link_target(self):
84        return self.view.application_url('students')
85
86class StudentsBreadcrumb(Breadcrumb):
87    """A breadcrumb for the students container.
88    """
89    grok.context(IStudentsContainer)
90    title = u'Students'
91
92class SudyCourseBreadcrumb(Breadcrumb):
93    """A breadcrumb for the student study course.
94    """
95    grok.context(IStudentStudyCourse)
96    title = u'Study Course'
97
98class PaymentsBreadcrumb(Breadcrumb):
99    """A breadcrumb for the student payments folder.
100    """
101    grok.context(IStudentPayments)
102    title = u'Payments'
103
104class AccommodationBreadcrumb(Breadcrumb):
105    """A breadcrumb for the student accommodation folder.
106    """
107    grok.context(IStudentAccommodation)
108    title = u'Accommodation'
109
110class StudentsContainerPage(WAeUPPage):
111    """The standard view for student containers.
112    """
113    grok.context(IStudentsContainer)
114    grok.name('index')
115    grok.require('waeup.viewStudent')
116    grok.template('studentscontainerpage')
117    label = 'Student Section'
118    title = 'Students'
119    pnav = 4
120
121    def update(self, *args, **kw):
122        datatable.need()
123        form = self.request.form
124        self.hitlist = []
125        if 'searchterm' in form and form['searchterm']:
126            self.searchterm = form['searchterm']
127            self.searchtype = form['searchtype']
128        elif 'old_searchterm' in form:
129            self.searchterm = form['old_searchterm']
130            self.searchtype = form['old_searchtype']
131        else:
132            if 'search' in form:
133                self.flash('Empty search string.')
134            return
135        self.hitlist = search(query=self.searchterm,
136            searchtype=self.searchtype, view=self)
137        if not self.hitlist:
138            self.flash('No student found.')
139        return
140
141class StudentsContainerManageActionButton(ManageActionButton):
142    grok.order(1)
143    grok.context(IStudentsContainer)
144    grok.view(StudentsContainerPage)
145    grok.require('waeup.manageStudents')
146    text = 'Manage student section'
147
148
149class StudentsContainerManagePage(WAeUPPage):
150    """The manage page for student containers.
151    """
152    grok.context(IStudentsContainer)
153    grok.name('manage')
154    grok.require('waeup.manageStudents')
155    grok.template('studentscontainermanagepage')
156    pnav = 4
157    title = 'Manage student section'
158
159    @property
160    def label(self):
161        return self.title
162
163    def update(self, *args, **kw):
164        datatable.need()
165        form = self.request.form
166        self.hitlist = []
167        if 'searchterm' in form and form['searchterm']:
168            self.searchterm = form['searchterm']
169            self.searchtype = form['searchtype']
170        elif 'old_searchterm' in form:
171            self.searchterm = form['old_searchterm']
172            self.searchtype = form['old_searchtype']
173        else:
174            if 'search' in form:
175                self.flash('Empty search string.')
176            return
177        if not 'entries' in form:
178            self.hitlist = search(query=self.searchterm,
179                searchtype=self.searchtype, view=self)
180            if not self.hitlist:
181                self.flash('No student found.')
182            return
183        entries = form['entries']
184        if isinstance(entries, basestring):
185            entries = [entries]
186        deleted = []
187        for entry in entries:
188            if 'remove' in form:
189                del self.context[entry]
190                deleted.append(entry)
191        self.hitlist = search(query=self.searchterm,
192            searchtype=self.searchtype, view=self)
193        if len(deleted):
194            self.flash('Successfully removed: %s' % ', '.join(deleted))
195        return
196
197class StudentsContainerAddActionButton(AddActionButton):
198    grok.order(1)
199    grok.context(IStudentsContainer)
200    grok.view(StudentsContainerManagePage)
201    grok.require('waeup.manageStudents')
202    text = 'Add student'
203    target = 'addstudent'
204
205class StudentAddFormPage(WAeUPAddFormPage):
206    """Add-form to add a student.
207    """
208    grok.context(IStudentsContainer)
209    grok.require('waeup.manageStudents')
210    grok.name('addstudent')
211    grok.template('studentaddpage')
212    form_fields = grok.AutoFields(IStudent)
213    title = 'Students'
214    label = 'Add student'
215    pnav = 4
216
217    @grok.action('Create student record')
218    def addStudent(self, **data):
219        student = createObject(u'waeup.Student')
220        self.applyData(student, **data)
221        self.context.addStudent(student)
222        self.flash('Student record created.')
223        self.redirect(self.url(self.context[student.student_id], 'index'))
224        return
225
226class StudentBaseDisplayFormPage(WAeUPDisplayFormPage):
227    """ Page to display student base data
228    """
229    grok.context(IStudent)
230    grok.name('index')
231    grok.require('waeup.viewStudent')
232    grok.template('studentpage')
233    form_fields = grok.AutoFields(IStudentBase)
234    pnav = 4
235    title = 'Base Data'
236
237    @property
238    def label(self):
239        return '%s: Base Data' % self.context.name
240
241class StudentBaseManageActionButton(ManageActionButton):
242    grok.order(1)
243    grok.context(IStudent)
244    grok.view(StudentBaseDisplayFormPage)
245    grok.require('waeup.manageStudents')
246    text = 'Edit'
247    target = 'edit_base'
248
249class StudentBaseManageFormPage(WAeUPEditFormPage):
250    """ View to edit student base data
251    """
252    grok.context(IStudent)
253    grok.name('edit_base')
254    grok.require('waeup.manageStudents')
255    form_fields = grok.AutoFields(IStudentBase).omit('student_id')
256    grok.template('studentbasemanagepage')
257    label = 'Edit base data'
258    title = 'Base Data'
259    pnav = 4
260
261    def update(self):
262        datepicker.need() # Enable jQuery datepicker in date fields.
263        super(StudentBaseManageFormPage, self).update()
264        self.wf_info = IWorkflowInfo(self.context)
265        return
266
267    def getTransitions(self):
268        """Return a list of dicts of allowed transition ids and titles.
269
270        Each list entry provides keys ``name`` and ``title`` for
271        internal name and (human readable) title of a single
272        transition.
273        """
274        allowed_transitions = self.wf_info.getManualTransitions()
275        return [dict(name='', title='No transition')] +[
276            dict(name=x, title=y) for x, y in allowed_transitions]
277
278    @grok.action('Save')
279    def save(self, **data):
280        changed_fields = self.applyData(self.context, **data)
281        changed_fields = changed_fields.values()
282        fields_string = '+'.join(' + '.join(str(i) for i in b) for b in changed_fields)
283        self.context._p_changed = True
284        form = self.request.form
285        if form.has_key('transition') and form['transition']:
286            transition_id = form['transition']
287            self.wf_info.fireTransition(transition_id)
288        self.flash('Form has been saved.')
289        ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
290        if fields_string:
291            self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
292        return
293
294class StudentClearanceDisplayFormPage(WAeUPDisplayFormPage):
295    """ Page to display student clearance data
296    """
297    grok.context(IStudent)
298    grok.name('view_clearance')
299    grok.require('waeup.viewStudent')
300    form_fields = grok.AutoFields(IStudentClearance)
301    form_fields['date_of_birth'].custom_widget = FriendlyDateDisplayWidget('le')
302    title = 'Clearance Data'
303    pnav = 4
304
305    @property
306    def label(self):
307        return '%s: Clearance Data' % self.context.name
308
309class StudentClearanceManageActionButton(ManageActionButton):
310    grok.order(1)
311    grok.context(IStudent)
312    grok.view(StudentClearanceDisplayFormPage)
313    grok.require('waeup.manageStudents')
314    text = 'Edit'
315    target = 'edit_clearance'
316
317class StudentClearanceManageFormPage(WAeUPEditFormPage):
318    """ Page to edit student clearance data
319    """
320    grok.context(IStudent)
321    grok.name('edit_clearance')
322    grok.require('waeup.manageStudents')
323    form_fields = grok.AutoFields(IStudentClearance)
324    label = 'Edit clearance data'
325    title = 'Clearance Data'
326    pnav = 4
327
328    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
329
330    def update(self):
331        datepicker.need() # Enable jQuery datepicker in date fields.
332        return super(StudentClearanceManageFormPage, self).update()
333
334class StudentPersonalDisplayFormPage(WAeUPDisplayFormPage):
335    """ Page to display student personal data
336    """
337    grok.context(IStudent)
338    grok.name('view_personal')
339    grok.require('waeup.viewStudent')
340    form_fields = grok.AutoFields(IStudentPersonal)
341    title = 'Personal Data'
342    pnav = 4
343
344    @property
345    def label(self):
346        return '%s: Personal Data' % self.context.name
347
348class StudentPersonalManageActionButton(ManageActionButton):
349    grok.order(1)
350    grok.context(IStudent)
351    grok.view(StudentPersonalDisplayFormPage)
352    grok.require('waeup.manageStudents')
353    text = 'Edit'
354    target = 'edit_personal'
355
356class StudentPersonalManageFormPage(WAeUPEditFormPage):
357    """ Page to edit student clearance data
358    """
359    grok.context(IStudent)
360    grok.name('edit_personal')
361    grok.require('waeup.viewStudent')
362    form_fields = grok.AutoFields(IStudentPersonal)
363    label = 'Edit personal data'
364    title = 'Personal Data'
365    pnav = 4
366
367class StudyCourseDisplayFormPage(WAeUPDisplayFormPage):
368    """ Page to display the student study course data
369    """
370    grok.context(IStudentStudyCourse)
371    grok.name('index')
372    grok.require('waeup.viewStudent')
373    form_fields = grok.AutoFields(IStudentStudyCourse)
374    #grok.template('studycoursepage')
375    title = 'Study Course'
376    pnav = 4
377
378    @property
379    def label(self):
380        return '%s: Study Course' % self.context.__parent__.name
381
382class StudyCourseManageActionButton(ManageActionButton):
383    grok.order(1)
384    grok.context(IStudentStudyCourse)
385    grok.view(StudyCourseDisplayFormPage)
386    grok.require('waeup.manageStudents')
387    text = 'Edit'
388    target = 'edit'
389
390class StudyCourseManageFormPage(WAeUPEditFormPage):
391    """ Page to edit the student study course data
392    """
393    grok.context(IStudentStudyCourse)
394    grok.name('edit')
395    grok.require('waeup.manageStudents')
396    form_fields = grok.AutoFields(IStudentStudyCourse)
397    label = 'Edit clearance data'
398    title = 'Study Course'
399    label = 'Edit study course'
400    pnav = 4
401
402class PaymentsDisplayFormPage(WAeUPDisplayFormPage):
403    """ Page to display the student payments
404    """
405    grok.context(IStudentPayments)
406    grok.name('index')
407    grok.require('waeup.viewStudent')
408    form_fields = grok.AutoFields(IStudentPayments)
409    #grok.template('paymentspage')
410    title = 'Payments'
411    pnav = 4
412
413    @property
414    def label(self):
415        return '%s: Payments' % self.context.__parent__.name
416
417class AccommodationDisplayFormPage(WAeUPDisplayFormPage):
418    """ Page to display the student accommodation data
419    """
420    grok.context(IStudentAccommodation)
421    grok.name('index')
422    grok.require('waeup.viewStudent')
423    form_fields = grok.AutoFields(IStudentAccommodation)
424    #grok.template('accommodationpage')
425    title = 'Accommodation'
426    pnav = 4
427
428    @property
429    def label(self):
430        return '%s: Accommodation Data' % self.context.__parent__.name
431
432class StudentHistoryPage(WAeUPPage):
433    """ Page to display student clearance data
434    """
435    grok.context(IStudent)
436    grok.name('history')
437    grok.require('waeup.viewStudent')
438    grok.template('studenthistory')
439    title = 'History'
440    pnav = 4
441
442    @property
443    def label(self):
444        return '%s: History' % self.context.name
Note: See TracBrowser for help on using the repository browser.