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

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

Add viewlet manager 'StudentSitebar?' which is rendered in a block above the LeftSidebar? viewlet manager block. This viewlet manager replaces the plain action buttons recently implemented.

  • 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 students'
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
168    @property
169    def title(self):
170        return "Students"
171
172    @property
173    def label(self):
174        return self.title
175
176    def update(self, *args, **kw):
177        datatable.need()
178        form = self.request.form
179        self.hitlist = []
180        if 'searchterm' in form and form['searchterm']:
181            self.searchterm = form['searchterm']
182            self.searchtype = form['searchtype']
183        elif 'old_searchterm' in form:
184            self.searchterm = form['old_searchterm']
185            self.searchtype = form['old_searchtype']
186        else:
187            if 'search' in form:
188                self.flash('Empty search string.')
189            return
190        #import pdb; pdb.set_trace()
191        if not 'entries' in form:
192            self.hitlist = search(query=self.searchterm,
193                searchtype=self.searchtype, view=self)
194            if not self.hitlist:
195                self.flash('No student found.')
196            return
197        entries = form['entries']
198        if isinstance(entries, basestring):
199            entries = [entries]
200        deleted = []
201        for entry in entries:
202            if 'remove' in form:
203                del self.context[entry]
204                deleted.append(entry)
205        self.hitlist = search(query=self.searchterm,
206            searchtype=self.searchtype, view=self)
207        if len(deleted):
208            self.flash('Successfully removed: %s' % ', '.join(deleted))
209        return
210
211class StudentsContainerAddActionButton(AddActionButton):
212    grok.order(1)
213    grok.context(IStudentsContainer)
214    grok.view(StudentsContainerManagePage)
215    grok.require('waeup.manageStudents')
216    text = 'Add student'
217    target = 'addstudent'
218
219class StudentAddFormPage(WAeUPAddFormPage):
220    """Add-form to add a student.
221    """
222    grok.context(IStudentsContainer)
223    grok.require('waeup.manageStudents')
224    grok.name('addstudent')
225    grok.template('studentaddpage')
226    form_fields = grok.AutoFields(IStudent)
227    title = 'Students'
228    label = 'Add student'
229    pnav = 4
230
231    @grok.action('Create student record')
232    def addStudent(self, **data):
233        student_id = self.request.form.get('form.student_id')
234        student = createObject(u'waeup.Student')
235        student.student_id = student_id
236        self.applyData(student, **data)
237        #import pdb; pdb.set_trace()
238        try:
239            self.context.addStudent(student)
240        except KeyError:
241            self.flash('The student id chosen already exists.')
242            return
243        self.flash('Student record created.')
244        self.redirect(self.url(self.context[student_id], 'index'))
245        return
246
247class StudentBaseDisplayFormPage(WAeUPDisplayFormPage):
248    """ Page to display student base data
249    """
250    grok.context(IStudent)
251    grok.name('index')
252    grok.require('waeup.viewStudents')
253    grok.template('studentpage')
254    form_fields = grok.AutoFields(IStudentBase)
255    pnav = 4
256    title = 'Base Data'
257
258    @property
259    def label(self):
260        return '%s: Base Data' % self.context.name
261
262class StudentBaseManageActionButton(ManageActionButton):
263    grok.order(1)
264    grok.context(IStudent)
265    grok.view(StudentBaseDisplayFormPage)
266    grok.require('waeup.manageStudents')
267    text = 'Edit'
268    target = 'edit_base'
269
270class StudentBaseManageFormPage(WAeUPEditFormPage):
271    """ View to edit student base data
272    """
273    grok.context(IStudent)
274    grok.name('edit_base')
275    grok.require('waeup.manageStudents')
276    form_fields = grok.AutoFields(IStudentBase).omit('student_id')
277    grok.template('studentbasemanagepage')
278    label = 'Edit base data'
279    title = 'Base Data'
280    pnav = 4
281
282    def update(self):
283        datepicker.need() # Enable jQuery datepicker in date fields.
284        super(StudentBaseManageFormPage, self).update()
285        self.wf_info = IWorkflowInfo(self.context)
286        return
287
288    def getTransitions(self):
289        """Return a list of dicts of allowed transition ids and titles.
290
291        Each list entry provides keys ``name`` and ``title`` for
292        internal name and (human readable) title of a single
293        transition.
294        """
295        allowed_transitions = self.wf_info.getManualTransitions()
296        return [dict(name='', title='No transition')] +[
297            dict(name=x, title=y) for x, y in allowed_transitions]
298
299    @grok.action('Save')
300    def save(self, **data):
301        changed_fields = self.applyData(self.context, **data)
302        changed_fields = changed_fields.values()
303        fields_string = '+'.join(' + '.join(str(i) for i in b) for b in changed_fields)
304        self.context._p_changed = True
305        form = self.request.form
306        if form.has_key('transition') and form['transition']:
307            transition_id = form['transition']
308            self.wf_info.fireTransition(transition_id)
309        self.flash('Form has been saved.')
310        ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
311        self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
312        return
313
314class StudentClearanceDisplayFormPage(WAeUPDisplayFormPage):
315    """ Page to display student clearance data
316    """
317    grok.context(IStudent)
318    grok.name('view_clearance')
319    grok.require('waeup.viewStudents')
320    form_fields = grok.AutoFields(IStudentClearance)
321    title = 'Clearance Data'
322    pnav = 4
323
324    @property
325    def label(self):
326        return '%s: Clearance Data' % self.context.name
327
328class StudentClearanceManageActionButton(ManageActionButton):
329    grok.order(1)
330    grok.context(IStudent)
331    grok.view(StudentClearanceDisplayFormPage)
332    grok.require('waeup.manageStudents')
333    text = 'Edit'
334    target = 'edit_clearance'
335
336class StudentClearanceManageFormPage(WAeUPEditFormPage):
337    """ Page to edit student clearance data
338    """
339    grok.context(IStudent)
340    grok.name('edit_clearance')
341    grok.require('waeup.viewStudents')
342    form_fields = grok.AutoFields(IStudentClearance)
343    label = 'Edit clearance data'
344    title = 'Clearance Data'
345    pnav = 4
346
347class StudentPersonalDisplayFormPage(WAeUPDisplayFormPage):
348    """ Page to display student personal data
349    """
350    grok.context(IStudent)
351    grok.name('view_personal')
352    grok.require('waeup.viewStudents')
353    form_fields = grok.AutoFields(IStudentPersonal)
354    title = 'Personal Data'
355    pnav = 4
356
357    @property
358    def label(self):
359        return '%s: Personal Data' % self.context.name
360
361class StudentPersonalManageActionButton(ManageActionButton):
362    grok.order(1)
363    grok.context(IStudent)
364    grok.view(StudentPersonalDisplayFormPage)
365    grok.require('waeup.manageStudents')
366    text = 'Edit'
367    target = 'edit_personal'
368
369class StudentPersonalManageFormPage(WAeUPEditFormPage):
370    """ Page to edit student clearance data
371    """
372    grok.context(IStudent)
373    grok.name('edit_personal')
374    grok.require('waeup.viewStudents')
375    form_fields = grok.AutoFields(IStudentPersonal)
376    label = 'Edit personal data'
377    title = 'Personal Data'
378    pnav = 4
379
380class StudyCourseDisplayFormPage(WAeUPDisplayFormPage):
381    """ Page to display the student study course data
382    """
383    grok.context(IStudentStudyCourse)
384    grok.name('index')
385    grok.require('waeup.viewStudents')
386    form_fields = grok.AutoFields(IStudentStudyCourse)
387    #grok.template('studycoursepage')
388    title = 'Study Course'
389    pnav = 4
390
391    @property
392    def label(self):
393        return '%s: Study Course' % self.context.__parent__.name
394
395class PaymentsDisplayFormPage(WAeUPDisplayFormPage):
396    """ Page to display the student payments
397    """
398    grok.context(IStudentPayments)
399    grok.name('index')
400    grok.require('waeup.viewStudents')
401    form_fields = grok.AutoFields(IStudentPayments)
402    #grok.template('paymentspage')
403    title = 'Payments'
404    pnav = 4
405
406    @property
407    def label(self):
408        return '%s: Payments' % self.context.__parent__.name
409
410class AccommodationDisplayFormPage(WAeUPDisplayFormPage):
411    """ Page to display the student accommodation data
412    """
413    grok.context(IStudentAccommodation)
414    grok.name('index')
415    grok.require('waeup.viewStudents')
416    form_fields = grok.AutoFields(IStudentAccommodation)
417    #grok.template('accommodationpage')
418    title = 'Accommodation'
419    pnav = 4
420
421    @property
422    def label(self):
423        return '%s: Accommodation Data' % self.context.__parent__.name
424
425class StudentHistoryPage(WAeUPPage):
426    """ Page to display student clearance data
427    """
428    grok.context(IStudent)
429    grok.name('history')
430    grok.require('waeup.viewStudents')
431    grok.template('studenthistory')
432    title = 'History'
433    pnav = 4
434
435    @property
436    def label(self):
437        return '%s: History' % self.context.name
Note: See TracBrowser for help on using the repository browser.