Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tables.py @ 91cb6fb6

History | View | Annotate | Download (8 kB)

1
# Copyright 2011-2012 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
from django.utils.translation import ugettext as _
35
from django.utils.safestring import mark_safe
36
from django.template import Context, Template
37
from django.template.loader import render_to_string
38

    
39
from django_tables2 import A
40
import django_tables2 as tables
41

    
42
from astakos.im.models import *
43

    
44
DEFAULT_DATE_FORMAT = "d/m/Y"
45

    
46

    
47
MEMBER_STATUS_DISPLAY = {
48
    100: _('Owner'),
49
      0: _('Requested'),
50
      1: _('Pending'),
51
      2: _('Accepted'),
52
      3: _('Removing'),
53
      4: _('Removed'),
54
     -1: _('Unregistered'),
55
}
56

    
57
# Helper columns
58
class RichLinkColumn(tables.TemplateColumn):
59

    
60
    method = 'POST'
61

    
62
    confirm_prompt = _('Yes')
63
    cancel_prompt = _('No')
64
    confirm = True
65

    
66
    prompt = _('Confirm action ?')
67

    
68
    action_tpl = None
69
    action = _('Action')
70
    extra_context = lambda record, table, column: {}
71

    
72
    url = None
73
    url_args = ()
74
    resolve_func = None
75

    
76
    def __init__(self, *args, **kwargs):
77
        kwargs['template_name'] = kwargs.get('template_name',
78
                                             'im/table_rich_link_column.html')
79
        for attr in ['method', 'confirm_prompt',
80
                     'cancel_prompt', 'prompt', 'url',
81
                     'url_args', 'action', 'confirm',
82
                     'resolve_func', 'extra_context']:
83
            setattr(self, attr, kwargs.pop(attr, getattr(self, attr)))
84

    
85
        super(RichLinkColumn, self).__init__(*args, **kwargs)
86

    
87
    def render(self, record, table, value, bound_column, **kwargs):
88
        # If the table is being rendered using `render_table`, it hackily
89
        # attaches the context to the table as a gift to `TemplateColumn`. If
90
        # the table is being rendered via `Table.as_html`, this won't exist.
91
        context = getattr(table, 'context', Context())
92
        context.update(self.get_template_context(record, table, value,
93
                                                 bound_column, **kwargs))
94
        try:
95
            if self.template_code:
96
                return Template(self.template_code).render(context)
97
            else:
98
                return render_to_string(self.template_name, context)
99
        finally:
100
            context.pop()
101

    
102
    def get_confirm(self, record, table):
103
        if callable(self.confirm):
104
            return self.confirm(record, table)
105
        return self.confirm
106

    
107
    def resolved_url(self, record, table):
108
        if callable(self.url):
109
            return self.url(record, table)
110

    
111
        if not self.url:
112
            return '#'
113

    
114
        args = list(self.url_args)
115
        for index, arg in enumerate(args):
116
            if isinstance(arg, A):
117
                args[index] = arg.resolve(record)
118
        return reverse(self.url, args=args)
119

    
120
    def get_action(self, record, table):
121
        if callable(self.action):
122
            return self.action(record, table)
123
        return self.action
124

    
125
    def get_prompt(self, record, table):
126
        if callable(self.prompt):
127
            return self.prompt(record, table)
128
        return self.prompt
129

    
130
    def get_template_context(self, record, table, value, bound_column, **kwargs):
131
        context = {'default': bound_column.default,
132
                   'record': record,
133
                   'value': value,
134
                   'col': self,
135
                   'url': self.resolved_url(record, table),
136
                   'prompt': self.get_prompt(record, table),
137
                   'action': self.get_action(record, table),
138
                   'confirm': self.get_confirm(record, table)
139
                  }
140

    
141
        if self.extra_context:
142
            context.update(self.extra_context(record, table, self))
143

    
144
        return context
145

    
146

    
147
def action_extra_context(project, table, self):
148
    user = table.user
149
    url, action, confirm, prompt = '', '', True, ''
150
    append_url = ''
151

    
152
    if user.owns_project(project):
153
        url = 'astakos.im.views.project_update'
154
        action = _('Update')
155
        confirm = False
156
        prompt = ''
157
    elif user.is_project_member(project):
158
        url = 'astakos.im.views.project_leave'
159
        action = _('- Leave')
160
        confirm = True
161
        prompt = _('Are you sure you want to leave from the project ?')
162
    else:
163
        url = 'astakos.im.views.project_join'
164
        action = _('+ Join')
165
        confirm = True
166
        prompt = _('Are you sure you want to join this project ?')
167

    
168
    return {'action': action, 'confirm': confirm,
169
            'url': reverse(url, args=(project.pk, )) + append_url,
170
            'prompt': prompt}
171

    
172

    
173
# Table classes
174
class UserProjectApplicationsTable(tables.Table):
175

    
176
    def __init__(self, *args, **kwargs):
177
        self.user = None
178

    
179
        if 'request' in kwargs and kwargs.get('request').user:
180
            self.user = kwargs.get('request').user
181

    
182
        if 'user' in kwargs:
183
            self.user = kwargs.pop('user')
184

    
185
        super(UserProjectApplicationsTable, self).__init__(*args, **kwargs)
186

    
187
    name = tables.LinkColumn('astakos.im.views.project_detail', args=(A('pk'),))
188
    issue_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT)
189
    start_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT)
190
    state = tables.Column(verbose_name="Status")
191
    members_count = tables.Column(verbose_name=_("Enrolled"), default=0,
192
                                  sortable=False)
193
    membership_status = tables.Column(verbose_name=_("My status"), empty_values=(),
194
                                      orderable=False)
195
    project_action = RichLinkColumn(verbose_name=_('Action'),
196
                                    extra_context=action_extra_context,
197
                                    sortable=False)
198

    
199

    
200
    def render_membership_status(self, *args, **kwargs):
201
        return MEMBER_STATUS_DISPLAY.get(kwargs.get('record').user_status(self.user))
202

    
203
    class Meta:
204
        model = ProjectApplication
205
        fields = ('name', 'membership_status', 'issue_date', 'start_date',
206
                  'state', 'members_count')
207
        attrs = {'id': 'projects-list', 'class': 'my-projects alt-style'}
208
        caption = _('My projects')
209
        template = "im/table_render.html"
210

    
211

    
212
class ProjectApplicationMembersTable(tables.Table):
213
    name = tables.Column(accessor="person.last_name", verbose_name=_('Name'))
214
    status = tables.Column(accessor="state", verbose_name=_('Status'))
215

    
216

    
217
    def render_name(self, value, record, *args, **kwargs):
218
        return record.person.realname
219

    
220
    def render_status(self, value, *args, **kwargs):
221
        return MEMBER_STATUS_DISPLAY.get(value, 'Unknown')
222

    
223
    class Meta:
224
        template = "im/table_render.html"
225
        model = ProjectMembership
226
        fields = ('name', 'status')
227
        attrs = {'id': 'members-table', 'class': 'members-table alt-style'}
228