source: main/waeup.kofa/trunk/src/waeup/kofa/browser/viewlets.py @ 12248

Last change on this file since 12248 was 11862, checked in by Henrik Bettermann, 10 years ago

Add permission, page and button to mass-clear all students in a department.

  • Property svn:keywords set to Id
File size: 25.0 KB
Line 
1## $Id: viewlets.py 11862 2014-10-21 07:07:04Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import grok
19from urllib import urlencode
20from zope.i18n import translate
21from zope.component import getMultiAdapter, queryAdapter, getUtility
22from zope.interface import Interface
23from zope.location.interfaces import ISite
24from zope.traversing.browser import absoluteURL
25from waeup.kofa.browser.pages import (
26    UniversityPage, FacultiesContainerPage, DatacenterPage, FacultyPage,
27    DepartmentPage, CoursePage, CertificatePage, CertificateCoursePage,
28    UsersContainerPage, UserManageFormPage)
29from waeup.kofa.browser.interfaces import (
30    IFacultiesContainer, IFaculty, IDepartment, ICourse, ICertificate,
31    ICertificateCourse, IBreadcrumbContainer, IUniversity, IUsersContainer)
32from waeup.kofa.interfaces import (
33    IKofaUtils, IKofaObject, IKofaXMLExporter,
34    IKofaXMLImporter, IDataCenter, IUserAccount)
35from waeup.kofa.browser.layout import KofaPage, default_primary_nav_template
36from waeup.kofa.utils.helpers import get_user_account
37
38from waeup.kofa.interfaces import MessageFactory as _
39
40grok.templatedir('templates')
41grok.context(IKofaObject) # Make IKofaObject the default context
42
43class ManageSidebar(grok.ViewletManager):
44    grok.name('left_manage')
45
46class BreadCrumbManager(grok.ViewletManager):
47    grok.name('breadcrumbs')
48
49class LanguageManager(grok.ViewletManager):
50    grok.name('languages')
51
52class ActionBar(grok.ViewletManager):
53    grok.name('actionbar')
54
55class AdministrationTasks(grok.ViewletManager):
56    grok.name('admintasks')
57
58class WidgetsSlot(grok.ViewletManager):
59    grok.name('widgets')
60
61
62#
63# Baseclasses that give some defaults for really used viewlets.
64#
65class ActionButton(grok.Viewlet):
66    """A base for action buttons.
67
68    An action button provides an icon, some text, links to a
69    target and optionally an onclick event handler.
70    If you want to set a different text, icon or target name
71    for some active button below, just override the approriate
72    attribute in the concerned viewlet.
73
74    Action buttons provide by default dynamic attributes
75
76     * ``alt``
77          An alternative text for the icon. By default the same as
78          the text.
79
80     * ``icon_url``
81          The URL of the icon.
82
83     * ``target_url``
84          The URL of the link target.
85
86     * ``onclick``
87          An onclick Javascript event handler.
88
89    """
90    grok.baseclass()
91    grok.context(IKofaObject)
92    grok.viewletmanager(ActionBar)
93    icon = 'actionicon_modify.png' # File must exist in static/
94    target = '@@manage' # link to this viewname.
95    text = _('Edit') # Text to display on the button
96
97    # We set the template file explicitly (instead of using
98    # ``grok.template('actionbutton')``) to stick with this template
99    # also in derived classes in other packages. If we didn't, those
100    # derived ActionButton viewlets had to provide an own template,
101    # which would not be updated automatically, when the local
102    # template ``templates/actionbutton.pt`` changes.
103    #
104    # Inheriting viewlets that wish to use their own template anyway
105    # can do so by setting their local ``grok.template(<mytemplate>)``
106    # and setting ``template`` to ``None`` for the class::
107    #
108    # class DerivedActionButton(ActionButton):
109    #   ...
110    #   grok.template('overriding_template')
111    #   template = None
112    #   ...
113    #
114    template = grok.PageTemplateFile('templates/actionbutton.pt')
115
116    @property
117    def alt(self):
118        """Alternative text for icon.
119        """
120        return self.text
121
122    @property
123    def icon_url(self):
124        """Get the icon URL.
125        """
126        return '/static/img/%s' % self.icon
127
128    @property
129    def target_url(self):
130        """Get a URL to the target...
131        """
132        if self.target:
133            return self.view.url(self.view.context, self.target)
134        return
135
136    @property
137    def onclick(self):
138        """Onclick event...
139        """
140        return
141
142class PlainActionButton(ActionButton):
143    """A base for action buttons without image
144    """
145    grok.baseclass()
146    template = grok.PageTemplateFile('templates/plainactionbutton.pt')
147
148   
149class ManageActionButton(ActionButton):
150    """A base for 'edit' buttons
151    """
152    grok.baseclass()
153    grok.order(2)
154    grok.require('waeup.manageAcademics')
155    icon = 'actionicon_modify.png'
156    target = '@@manage'
157    text = _('Edit')
158
159class AddActionButton(ActionButton):
160    """A base for 'add' buttons.
161    """
162    grok.baseclass()
163    grok.order(4)
164    grok.require('waeup.manageAcademics')
165    icon = 'actionicon_add.png'
166    target = 'add'
167    text = _('Add')
168   
169class RemoveActionButton(ActionButton):
170    """A base for 'remove' buttons.
171    """
172    grok.baseclass()
173    grok.order(4)
174    grok.require('waeup.manageAcademics')
175    icon = 'actionicon_delete.png'
176    target = 'remove'
177    text = _('Remove')
178
179class SearchActionButton(ActionButton):
180    """A base for 'search' buttons.
181    """
182    grok.baseclass()
183    grok.order(5)
184    grok.require('waeup.manageAcademics')
185    icon = 'actionicon_search.png'
186    target = 'search'
187    text = _('Search')
188
189
190#
191# General viewlets (for more than one page/context)
192#
193
194class BreadCrumbs(grok.Viewlet):
195    grok.context(IKofaObject)
196    grok.viewletmanager(BreadCrumbManager)
197    grok.order(1)
198
199    def getEntries(self):
200        result = []
201        site = grok.getSite()
202        context = self.context
203        breadcrumbs = IBreadcrumbContainer(self.view)
204        for breadcrumb in breadcrumbs:
205            if breadcrumb.target is None:
206                yield dict(
207                    title = breadcrumb.title,
208                    url = self.view.url(breadcrumb.context)
209                    )
210            elif breadcrumb.target:
211                yield dict(
212                    title = breadcrumb.title,
213                    url = self.view.url(breadcrumb.context, breadcrumb.target)
214                    )
215
216class LanguagesLink(grok.Viewlet):
217    """ The language selector itself.
218    """
219    grok.viewletmanager(LanguageManager)
220    grok.context(IKofaObject)
221    grok.require('waeup.Public')
222    title = u'Languages'
223
224    def render(self):
225        preferred_languages = getUtility(IKofaUtils).PREFERRED_LANGUAGES_DICT
226        html = u''
227        for key, value in sorted(
228            preferred_languages.items(), key=lambda lang: lang[1][0]):
229            args = {'lang':key, 'view_name':self.view.__name__}
230            url = self.view.url(
231                self.context) + '/@@change_language?%s' % urlencode(args)
232            html += u'| <a href="%s" title="%s">%s</a> ' % (url, value[1], key)
233        return html
234
235# Problem with circular references. Disabled for now...
236# class ExportXMLAction(grok.Viewlet):
237#    grok.viewletmanager(ActionBar)
238#     #grok.view(Index)
239#     grok.order(98)
240#     grok.require('waeup.managePortal')
241
242#class ImportXMLAction(grok.Viewlet):
243#    grok.viewletmanager(ActionBar)
244#    #grok.view(Index)
245#    grok.order(99)
246#    grok.require('waeup.managePortal')
247#
248#    def update(self):
249#        # We cannot simply replace local sites.
250#        self.can_import = not ISite.providedBy(self.context)
251
252
253class WidgetsTableRows(grok.Viewlet):
254    """The only viewlet for the WidgetsSlot viewlet manager.
255    """
256    template = grok.PageTemplateFile('templates/widgets.pt')
257    grok.viewletmanager(WidgetsSlot)
258
259
260class Login(grok.Viewlet):
261    """This viewlet allows to login in the sidebar.
262    """
263    grok.viewletmanager(ManageSidebar)
264    grok.context(IKofaObject)
265    grok.view(Interface)
266    grok.order(2)
267    grok.require('waeup.Anonymous')
268    text = _('Login')
269    link = 'login'
270
271    def render(self):
272        if self.request.principal.id != 'zope.anybody':
273            return ''
274        url = self.view.url(grok.getSite(), self.link)
275        return u'<li"><a href="%s">%s</a></li>' % (
276                url, self.text)
277
278
279class ManageLink(grok.Viewlet):
280    """A link displayed in the upper left box.
281
282    This viewlet renders a link to the application object's settings
283    form (the 'manage' view).
284
285    In derived classes you can create different links by setting a
286    different link and text attribute. The `link` parameter is
287    understood relative to the respective application object, so that
288    ``@@manage`` will create a link to
289    ``localhost:8080/app/@@manage``.
290
291    Links defined by descendants from this viewlet are displayed on
292    every page the user is allowed to go to, if the user has also the
293    permissions set by `grok.require()`. By default only users with
294    ``waeup.managePortal`` permission will see links defined by
295    this or derivated classes.
296    """
297    grok.baseclass()
298    grok.viewletmanager(ManageSidebar)
299    grok.context(IKofaObject)
300    grok.view(Interface)
301    grok.order(1)
302    # This link is only displayed, if the user is
303    # allowed to use it!
304    grok.require('waeup.managePortal')
305
306    link = 'relative_link'
307    text = _(u'Any link text')
308   
309    def render(self):
310        url = self.view.url(grok.getSite(), self.link)
311        text = translate(self.text, context=self.request)
312        return u'<li><a href="%s">%s</a></li>' % (
313                url, text)
314
315class ManagePortalConfiguration(ManageLink):
316    """A link to portal configuration.
317    """
318    grok.order(1)
319    grok.require('waeup.managePortalConfiguration')
320
321    link = 'configuration'
322    text = _(u'Portal Configuration')
323
324class ManageUsersLink(ManageLink):
325    """A link to users management, placed in upper left box.
326    """
327    grok.order(2)
328    grok.require('waeup.manageUsers')
329
330    link = u'users'
331    text = _(u'Portal Users')
332
333class ManageDataCenter(ManageLink):
334    """A link to datacenter, placed in upper left box.
335    """
336    grok.order(3)
337    grok.require('waeup.manageDataCenter')
338
339    link = u'datacenter'
340    text = _(u'Data Center')
341
342class ManageReports(ManageLink):
343    """A link to reports, placed in upper left box.
344    """
345    grok.order(4)
346    grok.require('waeup.manageReports')
347
348    link = u'reports'
349    text = _(u'Reports')
350
351class MyPreferences(ManageLink):
352    """A link to personal preferences, placed in upper left box.
353    """
354    grok.order(6)
355    grok.require('waeup.Public')
356    text = _(u'My Preferences')
357
358    def render(self):
359        account_object = get_user_account(self.request)
360        if account_object:
361            url = self.view.url(account_object)
362            text = translate(self.text, context=self.request)
363            return u'<li><a href="%s">%s</a></li>' % (
364                    url, text)
365        return ''
366
367class MyRoles(ManageLink):
368    """A link to display site and local roles.
369    """
370    grok.order(7)
371    grok.require('waeup.Public')
372    text = _(u'My Roles')
373
374    def render(self):
375        account_object = get_user_account(self.request)
376        if account_object:
377            url = self.view.url(account_object) + '/my_roles'
378            text = translate(self.text, context=self.request)
379            return u'<li><a href="%s">%s</a></li>' % (
380                    url, text)
381        return ''
382
383class ContactActionButton(ManageActionButton):
384    grok.order(4)
385    grok.context(IUserAccount)
386    grok.view(UserManageFormPage)
387    grok.require('waeup.manageUsers')
388    icon = 'actionicon_mail.png'
389    text = _('Send email')
390    target = 'contactuser'
391
392class ManageDataCenterActionButton(ManageActionButton):
393    """ 'Edit settings' button for datacenter.
394    """
395    grok.context(IDataCenter)
396    grok.view(DatacenterPage)
397    grok.require('waeup.managePortal')
398    text = _('Edit settings')
399    grok.order(1)
400
401class ManageFacultiesContainerActionButton(ManageActionButton):
402    """ 'Manage settings' button for faculties.
403    """
404    grok.context(IFacultiesContainer)
405    grok.view(FacultiesContainerPage)
406    text = _('Manage academic section')
407
408class ExportFacultiesStudentsActionButton(ManageActionButton):
409    """ 'Export student data' button for faculties.
410    """
411    grok.context(IFacultiesContainer)
412    grok.view(FacultiesContainerPage)
413    grok.name('exportfacultystudents')
414    grok.require('waeup.showStudents')
415    icon = 'actionicon_down.png'
416    text = _('Export student data')
417    target = 'exports'
418    grok.order(3)
419
420class SearchFacultiesContainerActionButton(ManageActionButton):
421    """ 'Manage settings' button for faculties.
422    """
423    grok.context(IFacultiesContainer)
424    grok.view(FacultiesContainerPage)
425    text = _('Search academic section')
426    icon = 'actionicon_search.png'
427    target = '@@search'
428   
429class ManageFacultyActionButton(ManageActionButton):
430    """ 'Manage settings' button for faculties.
431    """
432    grok.context(IFaculty)
433    grok.view(FacultyPage)
434    text = _('Manage faculty')
435
436class StudentSearchActionButton(ManageActionButton):
437    grok.order(2)
438    grok.context(IFaculty)
439    grok.view(FacultyPage)
440    grok.name('findstudents')
441    grok.require('waeup.showStudents')
442    text = _('Find students')
443    icon = 'actionicon_search.png'
444    target = 'find_students'
445
446class ManageDepartmentActionButton(ManageActionButton):
447    """ 'Manage settings' button for departments.
448    """
449    grok.context(IDepartment)
450    grok.view(DepartmentPage)
451    text = _('Manage department')
452    grok.order(1)
453
454class ShowDepartmentStudentsActionButton(ManageActionButton):
455    """ 'Show students' button for departments.
456    """
457    grok.context(IDepartment)
458    grok.view(DepartmentPage)
459    grok.name('showdepartmentstudents')
460    grok.require('waeup.showStudents')
461    icon = 'actionicon_student.png'
462    text = _('Show students')
463    target = 'students'
464    grok.order(2)
465
466class ExportDepartmentStudentsActionButton(ManageActionButton):
467    """ 'Export student data' button for departments.
468    """
469    grok.context(IDepartment)
470    grok.view(DepartmentPage)
471    grok.name('exportdepartmentstudents')
472    grok.require('waeup.showStudents')
473    icon = 'actionicon_down.png'
474    text = _('Export student data')
475    target = 'exports'
476    grok.order(3)
477
478class ClearDepartmentStudentsActionButton(ManageActionButton):
479    """ 'Clear all students' button for departments.
480    """
481    grok.context(IDepartment)
482    grok.view(DepartmentPage)
483    grok.name('cleardepartmentstudents')
484    grok.require('waeup.clearAllStudents')
485    icon = 'actionicon_accept.png'
486    text = _('Clear all students')
487    target = 'clearallstudents'
488    grok.order(4)
489
490    @property
491    def onclick(self):
492        return "return window.confirm(%s);" % _(
493            "'All students, who requested clearance in this department, will be cleared. Are you sure?'")
494
495class ManageCourseActionButton(ManageActionButton):
496    """ 'Edit settings' button for courses.
497    """
498    grok.context(ICourse)
499    grok.view(CoursePage)
500    text = _('Edit course')
501    grok.order(1)
502   
503class ShowCourseStudentsActionButton(ManageActionButton):
504    """ 'Show students' button in course.
505    """
506    grok.context(ICourse)
507    grok.view(CoursePage)
508    grok.name('showcoursestudents')
509    grok.require('waeup.showStudents')
510    icon = 'actionicon_student.png'
511    text = _('Show students')
512    target = 'students'
513    grok.order(2)
514
515class ExportCourseStudentsActionButton(ManageActionButton):
516    """ 'Export student data' button for courses.
517    """
518    grok.context(ICourse)
519    grok.view(CoursePage)
520    grok.name('exportcoursestudents')
521    grok.require('waeup.showStudents')
522    icon = 'actionicon_down.png'
523    text = _('Export student data')
524    target = 'exports'
525    grok.order(3)
526
527class UpdateScoresActionButton(ManageActionButton):
528    """ 'Update scores' button in course.
529    """
530    grok.context(ICourse)
531    grok.view(CoursePage)
532    grok.name('updatescores')
533    grok.require('waeup.editScores')
534    icon = 'actionicon_scores.png'
535    text = _('Update scores')
536    target = 'edit_scores'
537    grok.order(4)
538
539class ManageCertificateActionButton(ManageActionButton):
540    """ 'Manage settings' button for certificates.
541    """
542    grok.context(ICertificate)
543    grok.view(CertificatePage)
544    text = _('Manage certificate')
545    grok.order(1)
546
547class ShowCertificateStudentsActionButton(ManageActionButton):
548    """ 'Show students' button for certificates.
549    """
550    grok.context(ICertificate)
551    grok.view(CertificatePage)
552    grok.name('showcertificatestudents')
553    grok.require('waeup.showStudents')
554    icon = 'actionicon_student.png'
555    text = _('Show students')
556    target = 'students'
557    grok.order(2)
558
559class ExportCertificateStudentsActionButton(ManageActionButton):
560    """ 'Export student data' button for certificates.
561    """
562    grok.context(ICertificate)
563    grok.view(CertificatePage)
564    grok.name('exportcertificatestudents')
565    grok.require('waeup.showStudents')
566    icon = 'actionicon_down.png'
567    text = _('Export student data')
568    target = 'exports'
569    grok.order(3)
570
571class ManageCertificateCourseActionButton(ManageActionButton):
572    """ 'Manage settings' button for certificate courses.
573    """
574    grok.context(ICertificateCourse)
575    grok.view(CertificateCoursePage)
576    text = _('Edit certificate course')
577
578class AddUserActionButton(AddActionButton):
579    grok.require('waeup.manageUsers')
580    grok.context(IUsersContainer)
581    grok.view(UsersContainerPage)
582    text = _('Add user')
583
584class BrowseDatacenterLogs(ActionButton):
585    grok.context(IDataCenter)
586    grok.require('waeup.manageDataCenter')
587    grok.view(DatacenterPage)
588    grok.order(2)
589    icon = 'actionicon_info.png'
590    target = '@@logs'
591    text = _('Show logs')
592
593class UploadCSVButton(ActionButton):
594    grok.context(IDataCenter)
595    grok.view(DatacenterPage)
596    grok.require('waeup.manageDataCenter')
597    grok.order(3)
598    icon = 'actionicon_up.png'
599    target = '@@upload'
600    text = _('Upload data')
601
602class BatchOpButton(ActionButton):
603    grok.context(IDataCenter)
604    grok.view(DatacenterPage)
605    grok.require('waeup.manageDataCenter')
606    grok.order(4)
607    icon = 'actionicon_gear.png'
608    target = '@@import1'
609    text = _('Process data')
610
611class ExportCSVButton(ActionButton):
612    grok.context(IDataCenter)
613    grok.view(DatacenterPage)
614    grok.require('waeup.exportData')
615    grok.order(5)
616    icon = 'actionicon_down.png'
617    target = '@@export'
618    text = _('Export data')
619
620class BrowseFinishedFiles(ActionButton):
621    grok.context(IDataCenter)
622    grok.require('waeup.manageDataCenter')
623    grok.view(DatacenterPage)
624    grok.order(6)
625    icon = 'actionicon_finished.png'
626    target = '@@processed'
627    text = _('View processed files')
628
629#
630# Primary navigation tabs (in upper left navigation bar)...
631#
632class PrimaryNavManager(grok.ViewletManager):
633    """Viewlet manager for the primary navigation tab.
634    """
635    grok.name('primary_nav')
636
637class PrimaryNavTab(grok.Viewlet):
638    """Base for primary nav tabs.
639    """
640    grok.baseclass()
641    grok.viewletmanager(PrimaryNavManager)
642    grok.order(1)
643    grok.require('waeup.Public')
644    template = default_primary_nav_template
645
646    pnav = 0 # This is a kind of id of a tab. If some page provides
647             # also a 'pnav' attribute with the same value (here: 0),
648             # then the tab will be rendered as 'active' when the page
649             # gets rendered.
650             #
651             # This way you can assign certain pages to certain
652             # primary nav tabs. Each primary tab should therefore set
653             # the 'pnav' attribute to a different value (or several
654             # tabs might be rendered as active simultanously when the
655             # page gets rendered.
656    tab_title = u'Some Text'
657   
658    @property
659    def link_target(self):
660        return self.view.application_url()
661
662    @property
663    def active(self):
664        view_pnav = getattr(self.view, 'pnav', 0)
665        if view_pnav == self.pnav:
666            return 'active'
667        return ''
668
669#class HomeTab(PrimaryNavTab):
670#    """Home-tab in primary navigation.
671#    """
672#    grok.order(1)
673#    grok.require('waeup.Public')
674
675#    pnav = 0
676#    tab_title = u'Home'
677
678class FacultiesTab(PrimaryNavTab):
679    """Faculties-tab in primary navigation.
680    """
681    grok.order(2)
682    grok.require('waeup.viewAcademics')
683
684    pnav = 1
685    tab_title = _(u'Academics')
686
687    @property
688    def link_target(self):
689        return self.view.application_url('faculties')
690
691   
692class EnquiriesTab(PrimaryNavTab):
693    """Contact tab in primary navigation.
694
695    Display tab only for anonymous. Authenticated users can call a
696    contact form from the user navigation bar.
697    """
698    grok.order(6)
699    grok.require('waeup.Anonymous')
700    tab_title = _(u'Enquiries')
701    pnav = 2
702
703    # Also zope.manager has role Anonymous.
704    # To avoid displaying this tab, we have to check the principal id too.
705    @property
706    def link_target(self):
707        if self.request.principal.id == 'zope.anybody':
708            return self.view.application_url('enquiries')
709        return
710
711#
712# Administration tasks
713#
714class AdminTask(grok.Viewlet):
715    """The base for task entries on administration page.
716    """
717    grok.baseclass()
718    grok.order(1)
719    grok.viewletmanager(AdministrationTasks)
720    grok.require('waeup.managePortal')
721    grok.template('admintask')
722
723    link_title = 'Manage users' # How the link to the target will be titled.
724    target_viewname = 'users'   # The name of the target view.
725   
726    @property
727    def link_target(self):
728        return self.view.url(self.context[self.target_viewname])
729
730class AdminTaskPortalConfiguration(AdminTask):
731    """Entry on administration page that link to portal settings.
732    """
733    grok.order(1)
734    grok.require('waeup.managePortalConfiguration')
735
736    link_title = _('Portal Configuration')
737    def link_target(self):
738        return self.view.url(self.view.context, 'configuration')
739
740class AdminTaskUsers(AdminTask):
741    """Entry on administration page that link to user folder.
742    """
743    grok.order(2)
744    grok.require('waeup.manageUsers')
745
746    link_title = _('Portal Users')
747    target_viewname = 'users'
748   
749class AdminTaskDatacenter(AdminTask):
750    """Entry on administration page that link to datacenter.
751    """
752    grok.order(3)
753    grok.require('waeup.manageDataCenter')
754
755    link_title = _('Data Center')
756    target_viewname = 'datacenter'
757
758class AdminTaskReports(AdminTask):
759    """Entry on administration page that link to datacenter.
760    """
761    grok.order(3)
762    grok.require('waeup.manageReports')
763
764    link_title = _('Reports')
765    target_viewname = 'reports'
766
767# The SubobjectLister and its viewlets below are not used in Kofa.
768
769class SubobjectLister(grok.ViewletManager):
770    """Very special viewlet manager that displays lists of subobjects.
771    """
772    grok.name('subobjectlist')
773    grok.template('subobjectlist')
774
775    def update(self):
776        # The default implementation of update() sets self.viewlets to
777        # a list of viewlets for the current context
778        # (self.context). We make use of that fact by retrieving all
779        # viewlets for all items in our context container by simply
780        # setting these items as context while we call the default
781        # update() method. So we get a list of lists of viewlets for
782        # each item in a 'row' (where a single item is a row).
783        rows = []
784        orig_context = self.context
785        for name, value in self.context.items():
786            # Retrieve all viewlets for the current item (not the context)
787            self.context = value
788            super(SubobjectLister, self).update() # sets self.viewlets
789            rows.append(self.viewlets)
790            self.context = orig_context
791        self.rows = rows
792        # Finally, set the viewlets we would retrieve normally...
793        super(SubobjectLister, self).update()
794        return
795
796
797class FacultiesContainerListHead(grok.Viewlet):
798    """The header line of faculty container subobject lists.
799    """
800    grok.order(1)
801    grok.viewletmanager(SubobjectLister)
802    grok.context(IFacultiesContainer)
803    grok.require('waeup.viewAcademics')
804
805    def render(self):
806        return u'<th>Code</th><th>Title</th><th></th>'
807
808class FacultyListName(grok.Viewlet):
809    """Display a the title of a faculty as link in a list.
810    """
811    grok.order(1)
812    grok.viewletmanager(SubobjectLister)
813    grok.context(IFaculty)
814    grok.require('waeup.viewAcademics')
815
816    def render(self):
817        return u'<a href="%s">%s</a>' % (
818            self.view.url(self.context), self.context.__name__)
819
820class FacultyListTitle(grok.Viewlet):
821    """Display the title of a faculty in a list.
822    """
823    grok.order(2)
824    grok.viewletmanager(SubobjectLister)
825    grok.context(IFaculty)
826    grok.require('waeup.viewAcademics')
827
828    def render(self):
829        return self.context.title
830
831class FacultyRemoveButton(grok.Viewlet):
832    """Render a remove button for faculty lists.
833    """
834    grok.order(3)
835    grok.viewletmanager(SubobjectLister)
836    grok.context(IFaculty)
837    grok.require('waeup.manageAcademics')
838
839    def render(self):
840        return u'<div class="text-right"><form method="POST">' + \
841            '<input class="text-right" type="submit" value="remove" />' + \
842            '</form></div>'
Note: See TracBrowser for help on using the repository browser.