Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / templatetags / astakos_tags.py @ 058b6ec7

History | View | Annotate | Download (9.3 kB)

1
# Copyright 2011 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import urllib
35

    
36
from inspect import getargspec
37

    
38
from django import template
39
from django.core.urlresolvers import resolve
40
from django.conf import settings
41
from django.template import TemplateSyntaxError, Variable
42
from django.utils.translation import ugettext as _
43
from django.template.loader import render_to_string
44
from django.template import RequestContext
45
from django.core.urlresolvers import reverse
46
from django.utils.safestring import mark_safe
47

    
48
register = template.Library()
49

    
50
MESSAGES_VIEWS_MAP = getattr(settings, 'ASTAKOS_MESSAGES_VIEWS_MAP', {
51
    'astakos.im.views.index': 'LOGIN_MESSAGES',
52
    'astakos.im.views.logout': 'LOGIN_MESSAGES',
53
    'astakos.im.views.login': 'LOGIN_MESSAGES',
54
    'astakos.im.views.signup': 'SIGNUP_MESSAGES',
55
    'astakos.im.views.edit_profile': 'PROFILE_MESSAGES',
56
    'astakos.im.views.change_password': 'PROFILE_MESSAGES',
57
    'astakos.im.views.invite': 'PROFILE_MESSAGES',
58
    'astakos.im.views.feedback': 'PROFILE_MESSAGES',
59
})
60

    
61

    
62
# helper tag decorator
63
# https://github.com/djblets/djblets/blob/master/djblets/util/decorators.py#L96
64
def basictag(takes_context=False):
65
    """
66
    A decorator similar to Django's @register.simple_tag that optionally
67
    takes a context parameter. This condenses many tag implementations down
68
    to a few lines of code.
69

70
    Example:
71
        @register.tag
72
        @basictag(takes_context=True)
73
        def printuser(context):
74
            return context['user']
75
    """
76
    class BasicTagNode(template.Node):
77
        def __init__(self, take_context, tag_name, tag_func, args):
78
            self.takes_context = takes_context
79
            self.tag_name = tag_name
80
            self.tag_func = tag_func
81
            self.args = args
82

    
83
        def render(self, context):
84
            args = [Variable(var).resolve(context) for var in self.args]
85

    
86
            if self.takes_context:
87
                return self.tag_func(context, *args)
88
            else:
89
                return self.tag_func(*args)
90

    
91
    def basictag_func(tag_func):
92
        def _setup_tag(parser, token):
93
            bits = token.split_contents()
94
            tag_name = bits[0]
95
            del(bits[0])
96

    
97
            params, xx, xxx, defaults = getargspec(tag_func)
98
            max_args = len(params)
99

    
100
            if takes_context:
101
                if params[0] == 'context':
102
                    max_args -= 1 # Ignore context
103
                else:
104
                    raise TemplateSyntaxError, \
105
                        "Any tag function decorated with takes_context=True " \
106
                        "must have a first argument of 'context'"
107

    
108
            min_args = max_args - len(defaults or [])
109

    
110
            if not min_args <= len(bits) <= max_args:
111
                if min_args == max_args:
112
                    raise TemplateSyntaxError, \
113
                        "%r tag takes %d arguments." % (tag_name, min_args)
114
                else:
115
                    raise TemplateSyntaxError, \
116
                        "%r tag takes %d to %d arguments, got %d." % \
117
                        (tag_name, min_args, max_args, len(bits))
118

    
119
            return BasicTagNode(takes_context, tag_name, tag_func, bits)
120

    
121
        _setup_tag.__name__ = tag_func.__name__
122
        _setup_tag.__doc__ = tag_func.__doc__
123
        _setup_tag.__dict__.update(tag_func.__dict__)
124
        return _setup_tag
125

    
126
    return basictag_func
127

    
128

    
129
@register.tag(name='display_messages')
130
def display_messages(parser, token):
131
    return MessagesNode()
132

    
133

    
134
class DummyMessage(object):
135
    def __init__(self, type, msg):
136
        self.message = msg
137
        self.tags = type
138

    
139
    def __repr__(self):
140
        return "%s: %s" % (self.tags, self.message)
141

    
142

    
143
class MessagesNode(template.Node):
144

    
145
    def get_view_messages(self, context):
146
        messages = list(context['GLOBAL_MESSAGES'])
147
        try:
148
            view = resolve(context['request'].get_full_path())[0]
149
            view_name = "%s.%s" % (view.__module__, view.func_name)
150
            messages += context[MESSAGES_VIEWS_MAP.get(view_name)]
151
            return messages
152
        except Exception, e:
153
            return messages
154

    
155
    def render(self, context):
156
        if self not in context.render_context:
157
            messages = list(context['messages'])
158
            if context['EXTRA_MESSAGES_SET']:
159
                view_messages = self.get_view_messages(context)
160
                for msg_object in view_messages:
161
                    messages.append(DummyMessage(msg_object[0], msg_object[1]))
162

    
163
            if not messages:
164
                return ""
165

    
166
            cls = messages[-1].tags
167
            content = '<div class="top-msg active %s">' % cls
168
            for msg in messages:
169
                content += '<div class="msg %s">%s</div>' % (
170
                    msg.tags, msg.message)
171

    
172
            content += '<a href="#" title="close" class="close">X</a>'
173
            content += '</div>'
174
            context.render_context[self] = content
175

    
176
        return context.render_context[self]
177

    
178

    
179
@register.simple_tag
180
def get_grant_value(rname, form):
181
    grants = form.instance.grants
182
    service_name, resource_name = rname.split('.',1)
183
    try:
184
        return form.instance.projectresourcegrant_set.get(resource__name=resource_name,
185
                                                           resource__service__name=service_name).member_capacity
186
    except:
187
        return ''
188

    
189
@register.tag(name="provider_login_url")
190
@basictag(takes_context=True)
191
def provider_login_url(context, provider, from_login=False):
192
    request = context['request'].REQUEST
193
    next = request.get('next', None)
194
    code = request.get('code', None)
195
    key = request.get('key', None)
196

    
197
    attrs = {}
198
    if next:
199
        attrs['next'] = next
200
    if code:
201
        attrs['code'] = code
202
    if key:
203
        attrs['key'] = key
204
    if from_login:
205
        attrs['from_login'] = 1
206

    
207
    url = provider.add_url
208

    
209
    joinchar = "?"
210
    if "?" in url:
211
        joinchar = "&"
212

    
213
    return "%s%s%s" % (provider.add_url, joinchar, urllib.urlencode(attrs))
214

    
215

    
216
EXTRA_CONTENT_MAP = {
217
    'confirm_text': '<textarea name="reason"></textarea>'
218
}
219

    
220
CONFIRM_LINK_PROMPT_MAP = {
221
    'project_modification_cancel': _('Are you sure you want to dismiss this '
222
                                     'project ?'),
223
    'project_app_cancel': _('Are you sure you want to cancel this project ?'),
224
    'project_app_approve': _('Are you sure you want to approve this '
225
                             'project ?'),
226
    'project_app_deny': _('Are you sure you want to deny this project ? '
227
                          '<br /><br />You '
228
                          'may optionally provide denial reason in the '
229
                          'following field: <br /><br /><textarea class="deny_reason" '
230
                          'name="reason"></textarea>'),
231
    'project_app_dismiss': _('Are you sure you want to dismiss this '
232
                             'project ?'),
233
    'project_app_join': _('Are you sure you want to join this project ?'),
234
    'project_app_leave': _('Are you sure you want to leave this project ?'),
235
}
236

    
237

    
238
@register.tag(name="confirm_link")
239
@basictag(takes_context=True)
240
def confirm_link(context, title, prompt='', url=None, urlarg=None,
241
                 extracontent='',
242
                 confirm_prompt=None,
243
                 inline=True,
244
                 template="im/table_rich_link_column.html"):
245

    
246
    urlargs = None
247
    if urlarg:
248
        urlargs = (urlarg,)
249

    
250
    if CONFIRM_LINK_PROMPT_MAP.get(prompt, None):
251
        prompt = mark_safe(CONFIRM_LINK_PROMPT_MAP.get(prompt))
252

    
253
    url = reverse(url, args=urlargs)
254
    title = _(title)
255
    tpl_context = RequestContext(context.get('request'))
256
    tpl_context.update({
257
        'col': {
258
            'method': 'POST',
259
            'cancel_prompt': 'CANCEL',
260
            'confirm_prompt': confirm_prompt or title
261
        },
262
        'inline': inline,
263
        'url': url,
264
        'action': title,
265
        'prompt': prompt,
266
        'extra_form_content': EXTRA_CONTENT_MAP.get(extracontent, ''),
267
        'confirm': True
268
    })
269

    
270
    content = render_to_string(template, tpl_context)
271
    return content
272