Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / templatetags / astakos_tags.py @ 0156e40c

History | View | Annotate | Download (9.2 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
    try:
183
        r = form.instance.projectresourcegrant_set.get(resource__name=rname).member_capacity
184
    except Exception, e:
185
        r = ''
186
    return r
187

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

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

    
206
    url = provider.urls.get('login')
207

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

    
212
    return "%s%s%s" % (url, joinchar, urllib.urlencode(attrs))
213

    
214

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

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

    
236

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

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

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

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

    
269
    content = render_to_string(template, tpl_context)
270
    return content