## $Id: layout.py 7445 2012-01-10 10:43:18Z 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
##
"""Basic layout components.
"""
import os
import grok
from datetime import date, datetime
import grokcore.view
from cgi import escape
from zope.i18nmessageid import Message
from hurry.resource import mode
from megrok.layout import Page, Layout, Form, EditForm, DisplayForm, AddForm
from z3c.flashmessage.interfaces import IMessageSource, IMessageReceiver
from zope.component import getUtility, queryUtility, ComponentLookupError
from zope.formlib.utility import setUpWidgets
from grokcore.formlib.formlib import Action
from zope.interface import Interface
from zope.site.hooks import getSite
from waeup.sirp.interfaces import ISIRPObject, IUserAccount
from waeup.sirp.browser.interfaces import ITheme
from waeup.sirp.browser.theming import get_all_themes, SIRPThemeBase
from waeup.sirp.students.interfaces import IStudentNavigation
from waeup.sirp.applicants.interfaces import IApplicant
from waeup.sirp.authentication import get_principal_role_manager
grok.templatedir('templates')
default_waeup_display_template = grokcore.view.PageTemplateFile(
os.path.join('templates', 'default_waeup_display_form.pt'))
default_waeup_display_template.__grok_name__ = 'default_waeup_display_form'
default_waeup_edit_template = grokcore.view.PageTemplateFile(
os.path.join('templates', 'default_waeup_edit_form.pt'))
default_waeup_edit_template.__grok_name__ = 'default_waeup_edit_form'
default_primary_nav_template = grokcore.view.PageTemplateFile(
os.path.join('templates', 'primarynavtab.pt'))
default_primary_nav_template.__grok_name__ = 'default_primary_nav'
class action(grok.action):
def __call__(self, success):
action = SIRPAction(self.label, success=success, **self.options)
self.actions.append(action)
return action
class SIRPAction(Action):
def __init__(self, label, style='', **options):
super(SIRPAction, self).__init__(label, **options)
self.style = style
def render(self):
if not self.available():
return ''
label = self.label
if isinstance(label, Message):
label = zope.i18n.translate(self.label, context=self.form.request)
return ('' %
(self.__name__, self.__name__, escape(label, quote=True),
self.style))
class jsaction(grok.action):
def __call__(self, success):
action = JSAction(self.label, success=success, **self.options)
self.actions.append(action)
return action
class JSAction(Action):
msg = '\'Are you sure?\''
def render(self):
if not self.available():
return ''
label = self.label
if isinstance(label, Message):
label = zope.i18n.translate(self.label, context=self.form.request)
return ('' %
(self.__name__, self.__name__, escape(label, quote=True), self.msg)
)
def NullValidator(*args, **kw):
"""A validator that does not validate.
This is needed especially for cancel buttons. We don't want data
to be validated that will be thrown away in the next step.
You can use it with ``grok.action`` decorator like this::
@grok.action('Cancel', validator=NullValidator)
def cancel(self, **data):
self.redirect()
"""
return dict()
class Messages(grok.View):
"""Display messages of message receivers.
"""
grok.context(Interface)
@property
def messages(self):
receiver = getUtility(IMessageReceiver)
return receiver.receive()
class UtilityView(object):
"""A view mixin with useful methods.
The ``pnav`` attribute (a number) tells, to which primary
navigation tab a page declares to belong.
"""
title = u'' # What appears in the content title...
pnav = 0 # Primary navigation index...
def application_url(self, name=None):
"""Return the URL of the nearest site.
"""
site = getSite()
#if not site:
# raise ComponentLookupError("No site found.")
return self.url(site, name)
def flash(self, message, type='alert-message warning'):
"""Send a short message to the user.
"""
source = queryUtility(IMessageSource, name='session')
if source is None:
return None
source.send(message, type)
return True
class SIRPLayout(UtilityView,Layout):
"""A megrok.layout.Layout with additional methods.
"""
grok.baseclass()
class SIRPForm(UtilityView,Form):
"""A megrok.layout.Form with additional methods.
"""
grok.baseclass()
def setUpWidgets(self,ignore_request=False):
super(SIRPForm,self).setUpWidgets(ignore_request)
if self.widgets.get('subject'):
self.widgets['subject'].displayWidth = 45
if self.widgets.get('body'):
self.widgets['body'].height = 10
if self.widgets.get('body'):
self.widgets['body'].width = 35
class SIRPPage(UtilityView,Page):
"""A megrok.layout page with additional methods.
"""
grok.baseclass()
class SIRPDisplayFormPage(UtilityView,DisplayForm):
"""A megrok.layout.DisplayForm with additional methods.
"""
grok.baseclass()
template = default_waeup_display_template
class SIRPEditFormPage(UtilityView,EditForm):
"""A megrok.layout.EditForm with additional methods.
"""
grok.baseclass()
template = default_waeup_edit_template
def setUpWidgets(self,ignore_request=False):
super(SIRPEditFormPage,self).setUpWidgets(ignore_request)
if self.widgets.get('title'):
self.widgets['title'].displayWidth = 80
if self.widgets.get('frontpage'):
self.widgets['frontpage'].width = 70
if self.widgets.get('phone'):
self.widgets['phone'].displayWidth = 13
if self.widgets.get('notice'):
self.widgets['notice'].height = 3
class SIRPAddFormPage(UtilityView,AddForm):
"""A megrok.layout.AddForm with additional methods.
"""
grok.baseclass()
template = default_waeup_edit_template
class SiteLayout(SIRPLayout):
""" The general site layout.
"""
grok.context(ISIRPObject)
#: An instance of the default theme to use for the site layout
default_theme = SIRPThemeBase()
stafftemp = grok.PageTemplateFile('templates/staffsitelayout.pt')
studenttemp = grok.PageTemplateFile('templates/studentsitelayout.pt')
@property
def site(self):
return grok.getSite()
def getAppTitle(self):
return getattr(grok.getSite()['configuration'], 'name', u'Sample University')
def isAuthenticated(self):
"""Return True if the calling user is authenticated.
"""
usertitle = self.request.principal.title
return usertitle != 'Unauthenticated User'
def getUserTitle(self):
"""Return principal title of current user.
"""
usertitle = self.request.principal.title
if usertitle == 'Unauthenticated User':
return u'Anonymous User'
return usertitle
def getUserId(self):
"""Return id of current user.
"""
userid = self.request.principal.id
return userid
def isStudent(self):
usertype = getattr(self.request.principal, 'user_type', None)
if not usertype:
return False
return self.request.principal.user_type == 'student'
def isApplicant(self):
usertype = getattr(self.request.principal, 'user_type', None)
if not usertype:
return False
return self.request.principal.user_type == 'applicant'
def getStudentName(self):
"""Return the student name.
"""
if IStudentNavigation.providedBy(self.context):
return self.context.getStudent().display_fullname
return
def getApplicantName(self):
"""Return the applicant name.
"""
if IApplicant.providedBy(self.context):
return self.context.fullname
return
def formatDatetime(self,datetimeobj):
if isinstance(datetimeobj, datetime):
return datetimeobj.strftime("%Y-%m-%d %H:%M:%S")
else:
return None
def update(self):
"""Include the resources required by the chosen skin/theme.
University instances provide a 'skin' attribute, that should
hold the internal name of a theme.
A theme in the waeup.sirp sense consists of a list of
CSS/JavaScript resources defined in the
:mod:`waeup.sirp.browser.resources` module.
If the context University object has no such attribute or the
set value is not a valid theme name, we pick 'gray waeup
theme' as default.
"""
mode('minified')
theme_name = getattr(grok.getSite()['configuration'], 'skin', '')
theme = queryUtility(ITheme, name=theme_name,
default=self.default_theme)
for resource in theme.getResources():
resource.need()
return
def render(self):
if self.isStudent() or self.isApplicant() or not self.isAuthenticated():
return self.studenttemp.render(self)
return self.stafftemp.render(self)