## $Id: layout.py 12634 2015-02-27 21:56:34Z 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 from grokcore.view import PageTemplateFile from grokcore.formlib.formlib import Action from cgi import escape from zope.i18n import translate from zope.i18nmessageid import Message 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 zope.interface import Interface from zope.site.hooks import getSite from waeup.ikoba.interfaces import IIkobaObject, IUserAccount, IIkobaUtils from waeup.ikoba.interfaces import MessageFactory as _ from waeup.ikoba.utils.helpers import to_timezone, format_date from waeup.ikoba.authentication import get_principal_role_manager from waeup.ikoba.browser.interfaces import ICustomerNavigationBase grok.templatedir('templates') default_waeup_display_template = PageTemplateFile( os.path.join('templates', 'default_waeup_display_form.pt')) default_waeup_display_template.__grok_name__ = 'default_waeup_display_form' default_waeup_edit_template = PageTemplateFile( os.path.join('templates', 'default_waeup_edit_form.pt')) default_waeup_edit_template.__grok_name__ = 'default_waeup_edit_form' default_primary_nav_template = PageTemplateFile( os.path.join('templates', 'primarynavtab.pt')) default_primary_nav_template.__grok_name__ = 'default_primary_nav' default_filedisplay_template = PageTemplateFile( os.path.join('templates', 'filedisplay.pt')) default_filedisplay_template.__grok_name__ = 'default_filedisplay' default_fileupload_template = PageTemplateFile( os.path.join('templates', 'fileupload.pt')) default_fileupload_template.__grok_name__ = 'default_fileupload' class action(grok.action): def __call__(self, success): action = IkobaAction(self.label, success=success, **self.options) self.actions.append(action) return action class IkobaAction(Action): def __init__(self, label, style='', tooltip='', warning='', **options): super(IkobaAction, self).__init__(label, **options) self.style = style self.tooltip = tooltip self.warning = warning if style == '': self.style = 'default' def render(self): if not self.available(): return '' label = self.label if isinstance(label, Message): label = translate(self.label, context=self.form.request) if self.warning: warning = translate(self.warning, context=self.form.request) self.warning = ' onclick="return window.confirm(\'%s\')"' % warning if self.tooltip: tooltip = translate(self.tooltip, context=self.form.request) self.tooltip = ' data-toggle="tooltip" title="%s"' % tooltip if self.style: style = ' class="btn btn-%s"' % self.style else: style = ' class="btn btn-default"' html = ('') return html class jsaction(grok.action): msg = _('Are you sure?') def __call__(self, success): action = IkobaAction(self.label, success=success, warning=self.msg, **self.options) self.actions.append(action) return action 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='success'): """Send a short message to the user. """ cssClass = 'alert alert-%s' % type source = queryUtility(IMessageSource, name='session') if source is None: return None source.send(message, cssClass) return True class IkobaLayout(UtilityView,Layout): """A megrok.layout.Layout with additional methods. """ grok.baseclass() class IkobaForm(UtilityView,Form): """A megrok.layout.Form with additional methods. """ grok.baseclass() def setUpWidgets(self,ignore_request=False): super(IkobaForm,self).setUpWidgets(ignore_request) # Width parameters will be overridden by Bootstrap # so we have to set the css class if self.widgets.get('body'): self.widgets['body'].height = 10 class IkobaPage(UtilityView,Page): """A megrok.layout page with additional methods. """ grok.baseclass() class IkobaDisplayFormPage(UtilityView,DisplayForm): """A megrok.layout.DisplayForm with additional methods. """ grok.baseclass() template = default_waeup_display_template hide_hint = True def large_text_field(widget): for i in ('body', 'frontpage', 'multilingual', 'condition'): if i in widget.name: return True return False class IkobaEditFormPage(UtilityView,EditForm): """A megrok.layout.EditForm with additional methods. """ grok.baseclass() template = default_waeup_edit_template def setUpWidgets(self,ignore_request=False): super(IkobaEditFormPage,self).setUpWidgets(ignore_request) for widget in self.widgets: if not large_text_field(widget): widget.height = 3 class IkobaAddFormPage(UtilityView,AddForm): """A megrok.layout.AddForm with additional methods. """ grok.baseclass() template = default_waeup_edit_template def setUpWidgets(self,ignore_request=False): super(IkobaAddFormPage,self).setUpWidgets(ignore_request) for widget in self.widgets: if not large_text_field(widget): widget.height = 3 class SiteLayout(IkobaLayout): """ The general site layout. """ grok.context(IIkobaObject) #: An instance of the default theme to use for the site layout stafftemp = grok.PageTemplateFile('templates/staffsitelayout.pt') customertemp = grok.PageTemplateFile('templates/customersitelayout.pt') @property def site(self): return grok.getSite() def getAppTitle(self): return getattr(grok.getSite()['configuration'], 'name', u'Sample Company') def getAppAcronym(self): return getattr(grok.getSite()['configuration'], 'acronym', u'Acronym') 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 isCustomer(self): usertype = getattr(self.request.principal, 'user_type', None) if not usertype: return False return self.request.principal.user_type == 'customer' def getCustomerName(self): """Return the customer name. """ if ICustomerNavigationBase.providedBy(self.context): return self.context.customer.display_fullname def formatDatetime(self,datetimeobj): if isinstance(datetimeobj, datetime): tz = getUtility(IIkobaUtils).tzinfo try: timestamp = to_timezone( datetimeobj, tz).strftime("%Y-%m-%d %H:%M:%S") except ValueError: return None return timestamp else: return None def formatDate(self,dateobj): return format_date(dateobj, self.request) def formatTZDate(self,datetimeobj): if isinstance(datetimeobj, datetime): tz = getUtility(IIkobaUtils).tzinfo date = to_timezone( datetimeobj, tz).strftime("%d/%m/%Y") return date else: return None def render(self): if self.isCustomer() or not self.isAuthenticated(): return self.customertemp.render(self) return self.stafftemp.render(self)