## $Id: viewlets.py 16465 2021-04-16 15:12:37Z henrik $
##
## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
import grok
from urllib import urlencode
from zope.component import getMultiAdapter, queryAdapter, getUtility
from zope.i18n import translate
from zope.interface import Interface
from zope.location.interfaces import ISite
from zope.traversing.browser import absoluteURL
from waeup.kofa.browser.interfaces import (
IFacultiesContainer, IFaculty, IDepartment, ICourse, ICertificate,
ICertificateCourse, IBreadcrumbContainer, IUniversity, IUsersContainer)
from waeup.kofa.browser.layout import KofaPage, default_primary_nav_template
from waeup.kofa.browser.pages import (
UniversityPage, FacultiesContainerPage, DatacenterPage, FacultyPage,
DepartmentPage, CoursePage, CertificatePage, CertificateCoursePage,
UsersContainerPage, UserManageFormPage, DatacenterImportStep1)
from waeup.kofa.students.browser import EditScoresPage
from waeup.kofa.interfaces import MessageFactory as _
from waeup.kofa.interfaces import (
IKofaUtils, IKofaObject,
IDataCenter, IUserAccount,
academic_sessions_vocab)
from waeup.kofa.utils.helpers import get_user_account
grok.templatedir('templates')
grok.context(IKofaObject) # Make IKofaObject the default context
[docs]class BreadCrumbManager(grok.ViewletManager):
grok.name('breadcrumbs')
[docs]class LanguageManager(grok.ViewletManager):
grok.name('languages')
[docs]class ActionBar(grok.ViewletManager):
grok.name('actionbar')
[docs]class AdministrationTasks(grok.ViewletManager):
grok.name('admintasks')
[docs]class SourcesLeft(grok.ViewletManager):
grok.name('sources_left')
[docs]class SourcesRight(grok.ViewletManager):
grok.name('sources_right')
#
# Baseclasses that give some defaults for really used viewlets.
#
#
# General viewlets (for more than one page/context)
#
[docs]class BreadCrumbs(grok.Viewlet):
grok.context(IKofaObject)
grok.viewletmanager(BreadCrumbManager)
grok.order(1)
[docs] def getEntries(self):
result = []
site = grok.getSite()
context = self.context
breadcrumbs = IBreadcrumbContainer(self.view)
for breadcrumb in breadcrumbs:
if breadcrumb.target is None:
yield dict(
title = breadcrumb.title,
url = self.view.url(breadcrumb.context)
)
elif breadcrumb.target:
yield dict(
title = breadcrumb.title,
url = self.view.url(breadcrumb.context, breadcrumb.target)
)
[docs]class LanguagesLink(grok.Viewlet):
""" The language selector itself.
"""
grok.viewletmanager(LanguageManager)
grok.context(IKofaObject)
grok.require('waeup.Public')
title = u'Languages'
[docs] def render(self):
preferred_languages = getUtility(IKofaUtils).PREFERRED_LANGUAGES_DICT
html = u''
for key, value in sorted(
preferred_languages.items(), key=lambda lang: lang[1][0]):
args = {'lang':key, 'view_name':self.view.__name__}
url = self.view.url(
self.context) + '/@@change_language?%s' % urlencode(args)
html += u'| <a href="%s" title="%s">%s</a> ' % (url, value[1], key)
return html
[docs]class Login(grok.Viewlet):
"""This viewlet allows to login in the sidebar.
"""
grok.viewletmanager(ManageSidebar)
grok.context(IKofaObject)
grok.view(Interface)
grok.order(2)
grok.require('waeup.Anonymous')
text = _('Login')
link = 'login'
[docs] def render(self):
if self.request.principal.id != 'zope.anybody':
return ''
url = self.view.url(grok.getSite(), self.link)
return u'<li"><a href="%s">%s</a></li>' % (
url, self.text)
[docs]class ManageLink(grok.Viewlet):
"""A link displayed in the upper left box.
This viewlet renders a link to the application object's settings
form (the 'manage' view).
In derived classes you can create different links by setting a
different link and text attribute. The `link` parameter is
understood relative to the respective application object, so that
``@@manage`` will create a link to
``localhost:8080/app/@@manage``.
Links defined by descendants from this viewlet are displayed on
every page the user is allowed to go to, if the user has also the
permissions set by `grok.require()`. By default only users with
``waeup.managePortal`` permission will see links defined by
this or derivated classes.
"""
grok.baseclass()
grok.viewletmanager(ManageSidebar)
grok.context(IKofaObject)
grok.view(Interface)
grok.order(1)
# This link is only displayed, if the user is
# allowed to use it!
grok.require('waeup.managePortal')
link = 'relative_link'
text = _(u'Any link text')
[docs] def render(self):
url = self.view.url(grok.getSite(), self.link)
text = translate(self.text, context=self.request)
return u'<li><a href="%s">%s</a></li>' % (url, text)
[docs]class ManagePortalConfiguration(ManageLink):
"""A link to portal configuration.
"""
grok.order(1)
grok.require('waeup.managePortalConfiguration')
link = 'configuration'
text = _(u'Portal Configuration')
[docs]class ManageUsersLink(ManageLink):
"""A link to users management, placed in upper left box.
"""
grok.order(2)
grok.require('waeup.manageUsers')
link = u'users'
text = _(u'Officers')
[docs]class ManageDataCenter(ManageLink):
"""A link to datacenter, placed in upper left box.
"""
grok.order(3)
grok.require('waeup.manageDataCenter')
link = u'datacenter'
text = _(u'Data Center')
[docs]class ManageReports(ManageLink):
"""A link to reports, placed in upper left box.
"""
grok.order(4)
grok.require('waeup.handleReports')
link = u'reports'
text = _(u'Reports')
[docs]class LecturerCourses(ManageLink):
"""A link to courses of lecturers.
"""
grok.order(6)
grok.require('waeup.Authenticated')
link = u'my_courses'
text = _(u'My Courses')
[docs] def render(self):
user_account = get_user_account(self.request)
if user_account:
local_roles = user_account.getLocalRoles()
if local_roles.has_key('waeup.local.Lecturer'):
url = self.view.url(grok.getSite(), self.link)
text = translate(self.text, context=self.request)
return u'<li><a href="%s">%s</a></li>' % (url, text)
return ''
[docs]class TranscriptOfficerStudents(ManageLink):
"""A link to transcript requests.
"""
grok.order(6)
grok.require('waeup.Authenticated')
link = u'my_transcript_requests'
text = _(u'My ToDoList')
[docs] def render(self):
user_account = get_user_account(self.request)
if user_account:
local_roles = user_account.getLocalRoles()
site_roles = user_account.roles
if local_roles.has_key('waeup.local.TranscriptOfficer') \
or 'waeup.TranscriptOfficer' in site_roles:
url = self.view.url(grok.getSite(), self.link)
text = translate(self.text, context=self.request)
return u'<li><a href="%s">%s</a></li>' % (url, text)
return ''
[docs]class TranscriptSigneeStudents(ManageLink):
"""A link to transcript signing requests.
"""
grok.order(6)
grok.require('waeup.Authenticated')
link = u'my_transcript_signing_requests'
text = _(u'My ToDoList')
[docs] def render(self):
user_account = get_user_account(self.request)
if user_account:
local_roles = user_account.getLocalRoles()
if local_roles.has_key('waeup.local.TranscriptSignee'):
url = self.view.url(grok.getSite(), self.link)
text = translate(self.text, context=self.request)
return u'<li><a href="%s">%s</a></li>' % (url, text)
return ''
[docs]class MyPreferences(ManageLink):
"""A link to personal preferences, placed in upper left box.
"""
grok.order(7)
grok.require('waeup.Public')
text = _(u'My Preferences')
[docs] def render(self):
account_object = get_user_account(self.request)
if account_object:
url = self.view.url(account_object)
text = translate(self.text, context=self.request)
return u'<li><a href="%s">%s</a></li>' % (url, text)
return ''
[docs]class MyRoles(ManageLink):
"""A link to display site and local roles.
"""
grok.order(8)
grok.require('waeup.Public')
text = _(u'My Roles')
[docs] def render(self):
account_object = get_user_account(self.request)
if account_object:
url = self.view.url(account_object) + '/my_roles'
text = translate(self.text, context=self.request)
return u'<li><a href="%s">%s</a></li>' % (url, text)
return ''
#class RemoveFlashDepartmentStudentsActionButton(ManageActionButton):
# """ 'Remove all flash notices' button for departments.
# """
# grok.context(IDepartment)
# grok.view(DepartmentPage)
# grok.name('removeflashdepartmentstudents')
# grok.require('waeup.manageStudent')
# icon = 'actionicon_wipe.png'
# text = _('Remove all flash notices')
# target = 'removeflash'
# grok.order(5)
# @property
# def onclick(self):
# return "return window.confirm(%s);" % _(
# "'Flash notices of all students in this department will be removed. Are you sure?'")
[docs]class BrowseDatacenterLogs(ActionButton):
grok.context(IDataCenter)
grok.require('waeup.manageDataCenter')
grok.view(DatacenterPage)
grok.order(2)
icon = 'actionicon_info.png'
target = '@@logs'
text = _('Show logs')
[docs]class BrowseFinishedFiles(ActionButton):
grok.context(IDataCenter)
grok.require('waeup.manageDataCenter')
grok.view(DatacenterPage)
grok.order(6)
icon = 'actionicon_finished.png'
target = '@@processed'
text = _('View processed files')
[docs]class SwitchMaintMode(ActionButton):
grok.context(IDataCenter)
grok.require('waeup.importData')
#grok.view(DatacenterImportStep1)
grok.order(7)
icon = 'actionicon_stop.png'
target = 'switchmaintmode'
text = _('Switch maintenance mode')
@property
def onclick(self):
if grok.getSite()['configuration'].maintmode_enabled_by:
return
return "return window.confirm(%s);" % _(
"'In maintenance mode no other user can login, and "
"already logged-in users will be automatically logged out. "
"You will be the only logged-in user and you can safely start "
"any import. Please wait a few seconds before starting the import "
"so that all running processes are finished. "
"If the import is done, maintenance mode will "
"be automatically disabled. \\n\\n"
"You really want to enable maintenance mode?'")
#
# Primary navigation tabs (in upper left navigation bar)...
#
[docs]class PrimaryNavManager(grok.ViewletManager):
"""Viewlet manager for the primary navigation tab.
"""
grok.name('primary_nav')
[docs]class PrimaryNavTab(grok.Viewlet):
"""Base for primary nav tabs.
"""
grok.baseclass()
grok.viewletmanager(PrimaryNavManager)
grok.order(1)
grok.require('waeup.Public')
template = default_primary_nav_template
pnav = 0 # This is a kind of id of a tab. If some page provides
# also a 'pnav' attribute with the same value (here: 0),
# then the tab will be rendered as 'active' when the page
# gets rendered.
#
# This way you can assign certain pages to certain
# primary nav tabs. Each primary tab should therefore set
# the 'pnav' attribute to a different value (or several
# tabs might be rendered as active simultanously when the
# page gets rendered.
tab_title = u'Some Text'
@property
def link_target(self):
return self.view.application_url()
@property
def active(self):
view_pnav = getattr(self.view, 'pnav', 0)
if view_pnav == self.pnav:
return 'active'
return ''
#class HomeTab(PrimaryNavTab):
# """Home-tab in primary navigation.
# """
# grok.order(1)
# grok.require('waeup.Public')
# pnav = 0
# tab_title = u'Home'
[docs]class FacultiesTab(PrimaryNavTab):
"""Faculties-tab in primary navigation.
"""
grok.order(2)
grok.require('waeup.viewAcademics')
pnav = 1
tab_title = _(u'Academics')
@property
def link_target(self):
return self.view.application_url('faculties')
[docs]class EnquiriesTab(PrimaryNavTab):
"""Contact tab in primary navigation.
Display tab only for anonymous. Authenticated users can call a
contact form from the user navigation bar.
"""
grok.order(6)
grok.require('waeup.Anonymous')
tab_title = _(u'Enquiries')
pnav = 2
# Also zope.manager has role Anonymous.
# To avoid displaying this tab, we have to check the principal id too.
@property
def link_target(self):
if self.request.principal.id == 'zope.anybody':
return self.view.application_url('enquiries')
return
#
# Administration tasks
#
[docs]class AdminTask(grok.Viewlet):
"""The base for task entries on administration page.
"""
grok.baseclass()
grok.order(1)
grok.viewletmanager(AdministrationTasks)
grok.require('waeup.managePortal')
grok.template('admintask')
link_title = 'Manage users' # How the link to the target will be titled.
target_viewname = 'users' # The name of the target view.
@property
def link_target(self):
return self.view.url(self.context[self.target_viewname])
[docs]class AdminTaskPortalConfiguration(AdminTask):
"""Entry on administration page that link to portal settings.
"""
grok.order(1)
grok.require('waeup.managePortalConfiguration')
link_title = _('Portal Configuration')
[docs] def link_target(self):
return self.view.url(self.view.context, 'configuration')
[docs]class AdminTaskUsers(AdminTask):
"""Entry on administration page that link to user folder.
"""
grok.order(2)
grok.require('waeup.manageUsers')
link_title = _('Officers')
target_viewname = 'users'
[docs]class AdminTaskDatacenter(AdminTask):
"""Entry on administration page that link to datacenter.
"""
grok.order(3)
grok.require('waeup.manageDataCenter')
link_title = _('Data Center')
target_viewname = 'datacenter'
[docs]class AdminTaskReports(AdminTask):
"""Entry on administration page that link to datacenter.
"""
grok.order(3)
grok.require('waeup.manageReports')
link_title = _('Reports')
target_viewname = 'reports'
# The SubobjectLister and its viewlets below are not used in Kofa.
[docs]class SubobjectLister(grok.ViewletManager):
"""Very special viewlet manager that displays lists of subobjects.
"""
grok.name('subobjectlist')
grok.template('subobjectlist')
[docs] def update(self):
# The default implementation of update() sets self.viewlets to
# a list of viewlets for the current context
# (self.context). We make use of that fact by retrieving all
# viewlets for all items in our context container by simply
# setting these items as context while we call the default
# update() method. So we get a list of lists of viewlets for
# each item in a 'row' (where a single item is a row).
rows = []
orig_context = self.context
for name, value in self.context.items():
# Retrieve all viewlets for the current item (not the context)
self.context = value
super(SubobjectLister, self).update() # sets self.viewlets
rows.append(self.viewlets)
self.context = orig_context
self.rows = rows
# Finally, set the viewlets we would retrieve normally...
super(SubobjectLister, self).update()
return
[docs]class FacultiesContainerListHead(grok.Viewlet):
"""The header line of faculty container subobject lists.
"""
grok.order(1)
grok.viewletmanager(SubobjectLister)
grok.context(IFacultiesContainer)
grok.require('waeup.viewAcademics')
[docs] def render(self):
return u'<th>Code</th><th>Title</th><th></th>'
[docs]class FacultyListName(grok.Viewlet):
"""Display a the title of a faculty as link in a list.
"""
grok.order(1)
grok.viewletmanager(SubobjectLister)
grok.context(IFaculty)
grok.require('waeup.viewAcademics')
[docs] def render(self):
return u'<a href="%s">%s</a>' % (
self.view.url(self.context), self.context.__name__)
[docs]class FacultyListTitle(grok.Viewlet):
"""Display the title of a faculty in a list.
"""
grok.order(2)
grok.viewletmanager(SubobjectLister)
grok.context(IFaculty)
grok.require('waeup.viewAcademics')
[docs] def render(self):
return self.context.title
[docs]class InstTypesSource(grok.Viewlet):
"""Available institution types for the sources overview page.
"""
grok.order(1)
grok.viewletmanager(SourcesLeft)
grok.require('waeup.Public')
grok.template('source')
column = 'left'
name = 'InstTypes'
source_name = 'inst_types'
title = _('Institution Types')
[docs] def heading(self):
return 'heading%s' % self.name
[docs] def accordion(self):
return '#accordion-%s' % self.column
[docs] def collapse(self):
return 'collapse%s' % self.name
[docs] def hash_collapse(self):
return '#collapse%s' % self.name
[docs] def source(self):
return getattr(self.view, self.source_name)
[docs]class SessionSource(InstTypesSource):
"""Available sessions for the sources overview page.
"""
grok.order(2)
name = 'Sessions'
source_name = 'sessions'
title = _('Academic Sessions')
[docs]class CourseLevelSource(InstTypesSource):
"""Available course levels for the sources overview page.
"""
grok.order(3)
name = 'CourseLevels'
source_name = 'course_levels'
title = _('Course Levels')
[docs]class StudyLevelSource(InstTypesSource):
"""Available study levels for the sources overview page.
"""
grok.order(4)
name = 'StudyLevels'
source_name = 'study_levels'
title = _('Study Levels')
[docs]class StudyModeSource(InstTypesSource):
"""Available study modes for the sources overview page.
"""
grok.order(5)
name = 'StudyModes'
source_name = 'study_modes'
title = _('Study Modes')
[docs]class DegreeSource(InstTypesSource):
"""Available study modes for the sources overview page.
"""
grok.order(6)
name = 'Degrees'
source_name = 'degrees'
title = _('Degrees')
[docs]class PaymentCatsSource(InstTypesSource):
"""Available payment categories for the sources overview page.
"""
grok.order(7)
name = 'PaymentCats'
source_name = 'payment_cats'
title = _('Payment Categories')
[docs]class AppTypesSource(InstTypesSource):
"""Available application types for the sources overview page.
"""
grok.order(8)
name = 'AppTypes'
source_name = 'app_types'
title = _('Application Types (Prefixes)')
[docs]class AppCatsSource(InstTypesSource):
"""Available application categories for the sources overview page.
"""
grok.order(9)
name = 'AppCats'
source_name = 'app_cats'
title = _('Application Categories')
[docs]class StudentStatesSource(InstTypesSource):
"""Available student sates for the sources overview page.
"""
grok.order(1)
grok.viewletmanager(SourcesRight)
column = 'right'
name = 'StudentStates'
source_name = 'student_states'
title = _('Student Registration States')
[docs]class VerdictsSource(InstTypesSource):
"""Available verdicts for the sources overview page.
"""
grok.order(2)
grok.viewletmanager(SourcesRight)
column = 'right'
name = 'Verdicts'
source_name = 'verdicts'
title = _('Verdicts')
[docs]class ExamSubjectsSource(InstTypesSource):
"""Available exam subjects for the sources overview page.
"""
grok.order(4)
grok.viewletmanager(SourcesRight)
column = 'right'
name = 'ExamSubjects'
source_name = 'exam_subjects'
title = _('Exam Subjects')
[docs]class ExamGradesSource(InstTypesSource):
"""Available exam grades for the sources overview page.
"""
grok.order(5)
grok.viewletmanager(SourcesRight)
column = 'right'
name = 'ExamGrades'
source_name = 'exam_grades'
title = _('Exam Grades')
[docs]class SexSource(InstTypesSource):
"""Available sex values for the sources overview page.
"""
grok.order(6)
grok.viewletmanager(SourcesRight)
column = 'right'
name = 'Sex'
source_name = 'sex'
title = _('Sex')
[docs]class DisablePaymentGroupSource(InstTypesSource):
"""Available payment groups for the sources overview page.
"""
grok.order(7)
grok.viewletmanager(SourcesRight)
column = 'right'
name = 'DisablePaymentGroups'
source_name = 'disable_payment_groups'
title = _('Disable Payment Groups')