source: main/waeup.ikoba/trunk/src/waeup/ikoba/browser/layout.py @ 12774

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

Show validity period on contract pages and slips.

  • Property svn:keywords set to Id
File size: 10.0 KB
Line 
1## $Id: layout.py 12634 2015-02-27 21:56:34Z 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##
18"""Basic layout components.
19"""
20import os
21import grok
22from datetime import date, datetime
23from grokcore.view import PageTemplateFile
24from grokcore.formlib.formlib import Action
25from cgi import escape
26from zope.i18n import translate
27from zope.i18nmessageid import Message
28from megrok.layout import Page, Layout, Form, EditForm, DisplayForm, AddForm
29from z3c.flashmessage.interfaces import IMessageSource, IMessageReceiver
30from zope.component import getUtility, queryUtility, ComponentLookupError
31from zope.formlib.utility import setUpWidgets
32from zope.interface import Interface
33from zope.site.hooks import getSite
34from waeup.ikoba.interfaces import IIkobaObject, IUserAccount, IIkobaUtils
35from waeup.ikoba.interfaces import MessageFactory as _
36from waeup.ikoba.utils.helpers import to_timezone, format_date
37from waeup.ikoba.authentication import get_principal_role_manager
38from waeup.ikoba.browser.interfaces import ICustomerNavigationBase
39
40grok.templatedir('templates')
41default_waeup_display_template = PageTemplateFile(
42    os.path.join('templates', 'default_waeup_display_form.pt'))
43default_waeup_display_template.__grok_name__ = 'default_waeup_display_form'
44
45default_waeup_edit_template = PageTemplateFile(
46    os.path.join('templates', 'default_waeup_edit_form.pt'))
47default_waeup_edit_template.__grok_name__ = 'default_waeup_edit_form'
48
49default_primary_nav_template = PageTemplateFile(
50    os.path.join('templates', 'primarynavtab.pt'))
51default_primary_nav_template.__grok_name__ = 'default_primary_nav'
52
53default_filedisplay_template = PageTemplateFile(
54    os.path.join('templates', 'filedisplay.pt'))
55default_filedisplay_template.__grok_name__ = 'default_filedisplay'
56
57default_fileupload_template = PageTemplateFile(
58    os.path.join('templates', 'fileupload.pt'))
59default_fileupload_template.__grok_name__ = 'default_fileupload'
60
61class action(grok.action):
62
63    def __call__(self, success):
64        action = IkobaAction(self.label, success=success, **self.options)
65        self.actions.append(action)
66        return action
67
68class IkobaAction(Action):
69
70    def __init__(self, label, style='', tooltip='', warning='', **options):
71        super(IkobaAction, self).__init__(label, **options)
72        self.style = style
73        self.tooltip = tooltip
74        self.warning = warning
75        if style == '':
76            self.style = 'default'
77
78    def render(self):
79        if not self.available():
80            return ''
81        label = self.label
82        if isinstance(label, Message):
83            label = translate(self.label, context=self.form.request)
84        if self.warning:
85            warning = translate(self.warning, context=self.form.request)
86            self.warning = ' onclick="return window.confirm(\'%s\')"' % warning
87        if self.tooltip:
88            tooltip = translate(self.tooltip, context=self.form.request)
89            self.tooltip = ' data-toggle="tooltip" title="%s"' % tooltip
90        if self.style:
91            style = ' class="btn btn-%s"' % self.style
92        else:
93            style = ' class="btn btn-default"'
94        html = ('<input type="submit" id="%s" name="%s" value="%s"' %
95                (self.__name__, self.__name__, escape(label, quote=True))
96                + style + self.tooltip + self.warning
97                + ' />')
98        return html
99
100class jsaction(grok.action):
101
102    msg = _('Are you sure?')
103
104    def __call__(self, success):
105        action = IkobaAction(self.label,
106                            success=success, warning=self.msg,
107                            **self.options)
108        self.actions.append(action)
109        return action
110
111def NullValidator(*args, **kw):
112    """A validator that does not validate.
113
114    This is needed especially for cancel buttons. We don't want data
115    to be validated that will be thrown away in the next step.
116
117    You can use it with ``grok.action`` decorator like this::
118
119      @grok.action('Cancel', validator=NullValidator)
120      def cancel(self, **data):
121        self.redirect(<whereever-you-go>)
122    """
123    return dict()
124
125class Messages(grok.View):
126    """Display messages of message receivers.
127    """
128
129    grok.context(Interface)
130
131    @property
132    def messages(self):
133        receiver = getUtility(IMessageReceiver)
134        return receiver.receive()
135
136class UtilityView(object):
137    """A view mixin with useful methods.
138
139    The ``pnav`` attribute (a number) tells, to which primary
140    navigation tab a page declares to belong.
141    """
142    title = u'' # What appears in the content title...
143    pnav = 0 # Primary navigation index...
144
145    def application_url(self, name=None):
146        """Return the URL of the nearest site.
147        """
148        site = getSite()
149        #if not site:
150        #    raise ComponentLookupError("No site found.")
151        return self.url(site, name)
152
153    def flash(self, message, type='success'):
154        """Send a short message to the user.
155        """
156        cssClass = 'alert alert-%s' % type
157        source = queryUtility(IMessageSource, name='session')
158        if source is None:
159            return None
160        source.send(message, cssClass)
161        return True
162
163class IkobaLayout(UtilityView,Layout):
164    """A megrok.layout.Layout with additional methods.
165    """
166    grok.baseclass()
167
168class IkobaForm(UtilityView,Form):
169    """A megrok.layout.Form with additional methods.
170    """
171    grok.baseclass()
172
173    def setUpWidgets(self,ignore_request=False):
174        super(IkobaForm,self).setUpWidgets(ignore_request)
175        # Width parameters will be overridden by Bootstrap
176        # so we have to set the css class
177        if self.widgets.get('body'):
178            self.widgets['body'].height = 10
179
180class IkobaPage(UtilityView,Page):
181    """A megrok.layout page with additional methods.
182    """
183    grok.baseclass()
184
185class IkobaDisplayFormPage(UtilityView,DisplayForm):
186    """A megrok.layout.DisplayForm with additional methods.
187    """
188    grok.baseclass()
189    template = default_waeup_display_template
190    hide_hint = True
191
192def large_text_field(widget):
193    for i in  ('body', 'frontpage', 'multilingual', 'condition'):
194        if i in widget.name:
195            return True
196    return False
197
198class IkobaEditFormPage(UtilityView,EditForm):
199    """A megrok.layout.EditForm with additional methods.
200    """
201    grok.baseclass()
202    template = default_waeup_edit_template
203
204    def setUpWidgets(self,ignore_request=False):
205        super(IkobaEditFormPage,self).setUpWidgets(ignore_request)
206        for widget in self.widgets:
207            if not large_text_field(widget):
208                widget.height = 3
209
210class IkobaAddFormPage(UtilityView,AddForm):
211    """A megrok.layout.AddForm with additional methods.
212    """
213    grok.baseclass()
214    template = default_waeup_edit_template
215
216    def setUpWidgets(self,ignore_request=False):
217        super(IkobaAddFormPage,self).setUpWidgets(ignore_request)
218        for widget in self.widgets:
219            if not large_text_field(widget):
220                widget.height = 3
221
222class SiteLayout(IkobaLayout):
223    """ The general site layout.
224    """
225    grok.context(IIkobaObject)
226
227    #: An instance of the default theme to use for the site layout
228    stafftemp = grok.PageTemplateFile('templates/staffsitelayout.pt')
229    customertemp = grok.PageTemplateFile('templates/customersitelayout.pt')
230
231    @property
232    def site(self):
233        return grok.getSite()
234
235    def getAppTitle(self):
236        return getattr(grok.getSite()['configuration'], 'name', u'Sample Company')
237
238    def getAppAcronym(self):
239        return getattr(grok.getSite()['configuration'], 'acronym', u'Acronym')
240
241    def isAuthenticated(self):
242        """Return True if the calling user is authenticated.
243        """
244        usertitle = self.request.principal.title
245        return usertitle != 'Unauthenticated User'
246
247    def getUserTitle(self):
248        """Return principal title of current user.
249        """
250        usertitle = self.request.principal.title
251        if usertitle == 'Unauthenticated User':
252            return u'Anonymous User'
253        return usertitle
254
255    def getUserId(self):
256        """Return id of current user.
257        """
258        userid = self.request.principal.id
259        return userid
260
261    def isCustomer(self):
262        usertype = getattr(self.request.principal, 'user_type', None)
263        if not usertype:
264            return False
265        return self.request.principal.user_type == 'customer'
266
267    def getCustomerName(self):
268        """Return the customer name.
269        """
270        if ICustomerNavigationBase.providedBy(self.context):
271            return self.context.customer.display_fullname
272
273    def formatDatetime(self,datetimeobj):
274        if isinstance(datetimeobj, datetime):
275            tz = getUtility(IIkobaUtils).tzinfo
276            try:
277                timestamp = to_timezone(
278                    datetimeobj, tz).strftime("%Y-%m-%d %H:%M:%S")
279            except ValueError:
280                return None
281            return timestamp
282        else:
283            return None
284
285    def formatDate(self,dateobj):
286        return format_date(dateobj, self.request)
287           
288    def formatTZDate(self,datetimeobj):
289        if isinstance(datetimeobj, datetime):
290            tz = getUtility(IIkobaUtils).tzinfo
291            date = to_timezone(
292                datetimeobj, tz).strftime("%d/%m/%Y")
293            return date
294        else:
295            return None         
296
297    def render(self):
298        if self.isCustomer() or not self.isAuthenticated():
299            return self.customertemp.render(self)
300        return self.stafftemp.render(self)
Note: See TracBrowser for help on using the repository browser.