Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (8 kB)

1 91cb6fb6 Kostas Papadimitriou
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 91cb6fb6 Kostas Papadimitriou
#
3 91cb6fb6 Kostas Papadimitriou
# Redistribution and use in source and binary forms, with or
4 91cb6fb6 Kostas Papadimitriou
# without modification, are permitted provided that the following
5 91cb6fb6 Kostas Papadimitriou
# conditions are met:
6 91cb6fb6 Kostas Papadimitriou
#
7 91cb6fb6 Kostas Papadimitriou
#   1. Redistributions of source code must retain the above
8 91cb6fb6 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
9 91cb6fb6 Kostas Papadimitriou
#      disclaimer.
10 91cb6fb6 Kostas Papadimitriou
#
11 91cb6fb6 Kostas Papadimitriou
#   2. Redistributions in binary form must reproduce the above
12 91cb6fb6 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
13 91cb6fb6 Kostas Papadimitriou
#      disclaimer in the documentation and/or other materials
14 91cb6fb6 Kostas Papadimitriou
#      provided with the distribution.
15 91cb6fb6 Kostas Papadimitriou
#
16 91cb6fb6 Kostas Papadimitriou
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 91cb6fb6 Kostas Papadimitriou
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 91cb6fb6 Kostas Papadimitriou
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 91cb6fb6 Kostas Papadimitriou
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 91cb6fb6 Kostas Papadimitriou
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 91cb6fb6 Kostas Papadimitriou
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 91cb6fb6 Kostas Papadimitriou
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 91cb6fb6 Kostas Papadimitriou
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 91cb6fb6 Kostas Papadimitriou
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 91cb6fb6 Kostas Papadimitriou
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 91cb6fb6 Kostas Papadimitriou
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 91cb6fb6 Kostas Papadimitriou
# POSSIBILITY OF SUCH DAMAGE.
28 91cb6fb6 Kostas Papadimitriou
#
29 91cb6fb6 Kostas Papadimitriou
# The views and conclusions contained in the software and
30 91cb6fb6 Kostas Papadimitriou
# documentation are those of the authors and should not be
31 91cb6fb6 Kostas Papadimitriou
# interpreted as representing official policies, either expressed
32 91cb6fb6 Kostas Papadimitriou
# or implied, of GRNET S.A.
33 5550bcfb Kostas Papadimitriou
34 5550bcfb Kostas Papadimitriou
from django.utils.translation import ugettext as _
35 91cb6fb6 Kostas Papadimitriou
from django.utils.safestring import mark_safe
36 91cb6fb6 Kostas Papadimitriou
from django.template import Context, Template
37 91cb6fb6 Kostas Papadimitriou
from django.template.loader import render_to_string
38 91cb6fb6 Kostas Papadimitriou
39 5550bcfb Kostas Papadimitriou
from django_tables2 import A
40 91cb6fb6 Kostas Papadimitriou
import django_tables2 as tables
41 91cb6fb6 Kostas Papadimitriou
42 5550bcfb Kostas Papadimitriou
from astakos.im.models import *
43 5550bcfb Kostas Papadimitriou
44 5550bcfb Kostas Papadimitriou
DEFAULT_DATE_FORMAT = "d/m/Y"
45 5550bcfb Kostas Papadimitriou
46 5550bcfb Kostas Papadimitriou
47 5550bcfb Kostas Papadimitriou
MEMBER_STATUS_DISPLAY = {
48 5550bcfb Kostas Papadimitriou
    100: _('Owner'),
49 5550bcfb Kostas Papadimitriou
      0: _('Requested'),
50 5550bcfb Kostas Papadimitriou
      1: _('Pending'),
51 5550bcfb Kostas Papadimitriou
      2: _('Accepted'),
52 5550bcfb Kostas Papadimitriou
      3: _('Removing'),
53 5550bcfb Kostas Papadimitriou
      4: _('Removed'),
54 5550bcfb Kostas Papadimitriou
     -1: _('Unregistered'),
55 5550bcfb Kostas Papadimitriou
}
56 5550bcfb Kostas Papadimitriou
57 91cb6fb6 Kostas Papadimitriou
# Helper columns
58 91cb6fb6 Kostas Papadimitriou
class RichLinkColumn(tables.TemplateColumn):
59 91cb6fb6 Kostas Papadimitriou
60 91cb6fb6 Kostas Papadimitriou
    method = 'POST'
61 91cb6fb6 Kostas Papadimitriou
62 91cb6fb6 Kostas Papadimitriou
    confirm_prompt = _('Yes')
63 91cb6fb6 Kostas Papadimitriou
    cancel_prompt = _('No')
64 91cb6fb6 Kostas Papadimitriou
    confirm = True
65 91cb6fb6 Kostas Papadimitriou
66 91cb6fb6 Kostas Papadimitriou
    prompt = _('Confirm action ?')
67 91cb6fb6 Kostas Papadimitriou
68 91cb6fb6 Kostas Papadimitriou
    action_tpl = None
69 91cb6fb6 Kostas Papadimitriou
    action = _('Action')
70 91cb6fb6 Kostas Papadimitriou
    extra_context = lambda record, table, column: {}
71 91cb6fb6 Kostas Papadimitriou
72 91cb6fb6 Kostas Papadimitriou
    url = None
73 91cb6fb6 Kostas Papadimitriou
    url_args = ()
74 91cb6fb6 Kostas Papadimitriou
    resolve_func = None
75 91cb6fb6 Kostas Papadimitriou
76 91cb6fb6 Kostas Papadimitriou
    def __init__(self, *args, **kwargs):
77 91cb6fb6 Kostas Papadimitriou
        kwargs['template_name'] = kwargs.get('template_name',
78 91cb6fb6 Kostas Papadimitriou
                                             'im/table_rich_link_column.html')
79 91cb6fb6 Kostas Papadimitriou
        for attr in ['method', 'confirm_prompt',
80 91cb6fb6 Kostas Papadimitriou
                     'cancel_prompt', 'prompt', 'url',
81 91cb6fb6 Kostas Papadimitriou
                     'url_args', 'action', 'confirm',
82 91cb6fb6 Kostas Papadimitriou
                     'resolve_func', 'extra_context']:
83 91cb6fb6 Kostas Papadimitriou
            setattr(self, attr, kwargs.pop(attr, getattr(self, attr)))
84 91cb6fb6 Kostas Papadimitriou
85 91cb6fb6 Kostas Papadimitriou
        super(RichLinkColumn, self).__init__(*args, **kwargs)
86 91cb6fb6 Kostas Papadimitriou
87 91cb6fb6 Kostas Papadimitriou
    def render(self, record, table, value, bound_column, **kwargs):
88 91cb6fb6 Kostas Papadimitriou
        # If the table is being rendered using `render_table`, it hackily
89 91cb6fb6 Kostas Papadimitriou
        # attaches the context to the table as a gift to `TemplateColumn`. If
90 91cb6fb6 Kostas Papadimitriou
        # the table is being rendered via `Table.as_html`, this won't exist.
91 91cb6fb6 Kostas Papadimitriou
        context = getattr(table, 'context', Context())
92 91cb6fb6 Kostas Papadimitriou
        context.update(self.get_template_context(record, table, value,
93 91cb6fb6 Kostas Papadimitriou
                                                 bound_column, **kwargs))
94 91cb6fb6 Kostas Papadimitriou
        try:
95 91cb6fb6 Kostas Papadimitriou
            if self.template_code:
96 91cb6fb6 Kostas Papadimitriou
                return Template(self.template_code).render(context)
97 91cb6fb6 Kostas Papadimitriou
            else:
98 91cb6fb6 Kostas Papadimitriou
                return render_to_string(self.template_name, context)
99 91cb6fb6 Kostas Papadimitriou
        finally:
100 91cb6fb6 Kostas Papadimitriou
            context.pop()
101 91cb6fb6 Kostas Papadimitriou
102 91cb6fb6 Kostas Papadimitriou
    def get_confirm(self, record, table):
103 91cb6fb6 Kostas Papadimitriou
        if callable(self.confirm):
104 91cb6fb6 Kostas Papadimitriou
            return self.confirm(record, table)
105 91cb6fb6 Kostas Papadimitriou
        return self.confirm
106 91cb6fb6 Kostas Papadimitriou
107 91cb6fb6 Kostas Papadimitriou
    def resolved_url(self, record, table):
108 91cb6fb6 Kostas Papadimitriou
        if callable(self.url):
109 91cb6fb6 Kostas Papadimitriou
            return self.url(record, table)
110 91cb6fb6 Kostas Papadimitriou
111 91cb6fb6 Kostas Papadimitriou
        if not self.url:
112 91cb6fb6 Kostas Papadimitriou
            return '#'
113 91cb6fb6 Kostas Papadimitriou
114 91cb6fb6 Kostas Papadimitriou
        args = list(self.url_args)
115 91cb6fb6 Kostas Papadimitriou
        for index, arg in enumerate(args):
116 91cb6fb6 Kostas Papadimitriou
            if isinstance(arg, A):
117 91cb6fb6 Kostas Papadimitriou
                args[index] = arg.resolve(record)
118 91cb6fb6 Kostas Papadimitriou
        return reverse(self.url, args=args)
119 91cb6fb6 Kostas Papadimitriou
120 91cb6fb6 Kostas Papadimitriou
    def get_action(self, record, table):
121 91cb6fb6 Kostas Papadimitriou
        if callable(self.action):
122 91cb6fb6 Kostas Papadimitriou
            return self.action(record, table)
123 91cb6fb6 Kostas Papadimitriou
        return self.action
124 91cb6fb6 Kostas Papadimitriou
125 91cb6fb6 Kostas Papadimitriou
    def get_prompt(self, record, table):
126 91cb6fb6 Kostas Papadimitriou
        if callable(self.prompt):
127 91cb6fb6 Kostas Papadimitriou
            return self.prompt(record, table)
128 91cb6fb6 Kostas Papadimitriou
        return self.prompt
129 91cb6fb6 Kostas Papadimitriou
130 91cb6fb6 Kostas Papadimitriou
    def get_template_context(self, record, table, value, bound_column, **kwargs):
131 91cb6fb6 Kostas Papadimitriou
        context = {'default': bound_column.default,
132 91cb6fb6 Kostas Papadimitriou
                   'record': record,
133 91cb6fb6 Kostas Papadimitriou
                   'value': value,
134 91cb6fb6 Kostas Papadimitriou
                   'col': self,
135 91cb6fb6 Kostas Papadimitriou
                   'url': self.resolved_url(record, table),
136 91cb6fb6 Kostas Papadimitriou
                   'prompt': self.get_prompt(record, table),
137 91cb6fb6 Kostas Papadimitriou
                   'action': self.get_action(record, table),
138 91cb6fb6 Kostas Papadimitriou
                   'confirm': self.get_confirm(record, table)
139 91cb6fb6 Kostas Papadimitriou
                  }
140 91cb6fb6 Kostas Papadimitriou
141 91cb6fb6 Kostas Papadimitriou
        if self.extra_context:
142 91cb6fb6 Kostas Papadimitriou
            context.update(self.extra_context(record, table, self))
143 91cb6fb6 Kostas Papadimitriou
144 91cb6fb6 Kostas Papadimitriou
        return context
145 91cb6fb6 Kostas Papadimitriou
146 91cb6fb6 Kostas Papadimitriou
147 91cb6fb6 Kostas Papadimitriou
def action_extra_context(project, table, self):
148 91cb6fb6 Kostas Papadimitriou
    user = table.user
149 91cb6fb6 Kostas Papadimitriou
    url, action, confirm, prompt = '', '', True, ''
150 91cb6fb6 Kostas Papadimitriou
    append_url = ''
151 91cb6fb6 Kostas Papadimitriou
152 91cb6fb6 Kostas Papadimitriou
    if user.owns_project(project):
153 91cb6fb6 Kostas Papadimitriou
        url = 'astakos.im.views.project_update'
154 91cb6fb6 Kostas Papadimitriou
        action = _('Update')
155 91cb6fb6 Kostas Papadimitriou
        confirm = False
156 91cb6fb6 Kostas Papadimitriou
        prompt = ''
157 91cb6fb6 Kostas Papadimitriou
    elif user.is_project_member(project):
158 91cb6fb6 Kostas Papadimitriou
        url = 'astakos.im.views.project_leave'
159 91cb6fb6 Kostas Papadimitriou
        action = _('- Leave')
160 91cb6fb6 Kostas Papadimitriou
        confirm = True
161 91cb6fb6 Kostas Papadimitriou
        prompt = _('Are you sure you want to leave from the project ?')
162 91cb6fb6 Kostas Papadimitriou
    else:
163 91cb6fb6 Kostas Papadimitriou
        url = 'astakos.im.views.project_join'
164 91cb6fb6 Kostas Papadimitriou
        action = _('+ Join')
165 91cb6fb6 Kostas Papadimitriou
        confirm = True
166 91cb6fb6 Kostas Papadimitriou
        prompt = _('Are you sure you want to join this project ?')
167 91cb6fb6 Kostas Papadimitriou
168 91cb6fb6 Kostas Papadimitriou
    return {'action': action, 'confirm': confirm,
169 91cb6fb6 Kostas Papadimitriou
            'url': reverse(url, args=(project.pk, )) + append_url,
170 91cb6fb6 Kostas Papadimitriou
            'prompt': prompt}
171 91cb6fb6 Kostas Papadimitriou
172 91cb6fb6 Kostas Papadimitriou
173 91cb6fb6 Kostas Papadimitriou
# Table classes
174 5550bcfb Kostas Papadimitriou
class UserProjectApplicationsTable(tables.Table):
175 5550bcfb Kostas Papadimitriou
176 5550bcfb Kostas Papadimitriou
    def __init__(self, *args, **kwargs):
177 5550bcfb Kostas Papadimitriou
        self.user = None
178 5550bcfb Kostas Papadimitriou
179 5550bcfb Kostas Papadimitriou
        if 'request' in kwargs and kwargs.get('request').user:
180 5550bcfb Kostas Papadimitriou
            self.user = kwargs.get('request').user
181 5550bcfb Kostas Papadimitriou
182 5550bcfb Kostas Papadimitriou
        if 'user' in kwargs:
183 5550bcfb Kostas Papadimitriou
            self.user = kwargs.pop('user')
184 5550bcfb Kostas Papadimitriou
185 5550bcfb Kostas Papadimitriou
        super(UserProjectApplicationsTable, self).__init__(*args, **kwargs)
186 5550bcfb Kostas Papadimitriou
187 5550bcfb Kostas Papadimitriou
    name = tables.LinkColumn('astakos.im.views.project_detail', args=(A('pk'),))
188 5550bcfb Kostas Papadimitriou
    issue_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT)
189 5550bcfb Kostas Papadimitriou
    start_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT)
190 5550bcfb Kostas Papadimitriou
    state = tables.Column(verbose_name="Status")
191 2743e261 Kostas Papadimitriou
    members_count = tables.Column(verbose_name=_("Enrolled"), default=0,
192 a5cef8d0 Kostas Papadimitriou
                                  sortable=False)
193 2743e261 Kostas Papadimitriou
    membership_status = tables.Column(verbose_name=_("My status"), empty_values=(),
194 5550bcfb Kostas Papadimitriou
                                      orderable=False)
195 91cb6fb6 Kostas Papadimitriou
    project_action = RichLinkColumn(verbose_name=_('Action'),
196 91cb6fb6 Kostas Papadimitriou
                                    extra_context=action_extra_context,
197 91cb6fb6 Kostas Papadimitriou
                                    sortable=False)
198 5550bcfb Kostas Papadimitriou
199 2743e261 Kostas Papadimitriou
200 5550bcfb Kostas Papadimitriou
    def render_membership_status(self, *args, **kwargs):
201 91cb6fb6 Kostas Papadimitriou
        return MEMBER_STATUS_DISPLAY.get(kwargs.get('record').user_status(self.user))
202 5550bcfb Kostas Papadimitriou
203 5550bcfb Kostas Papadimitriou
    class Meta:
204 5550bcfb Kostas Papadimitriou
        model = ProjectApplication
205 5550bcfb Kostas Papadimitriou
        fields = ('name', 'membership_status', 'issue_date', 'start_date',
206 5550bcfb Kostas Papadimitriou
                  'state', 'members_count')
207 2743e261 Kostas Papadimitriou
        attrs = {'id': 'projects-list', 'class': 'my-projects alt-style'}
208 2743e261 Kostas Papadimitriou
        caption = _('My projects')
209 2743e261 Kostas Papadimitriou
        template = "im/table_render.html"
210 2743e261 Kostas Papadimitriou
211 2743e261 Kostas Papadimitriou
212 2743e261 Kostas Papadimitriou
class ProjectApplicationMembersTable(tables.Table):
213 2743e261 Kostas Papadimitriou
    name = tables.Column(accessor="person.last_name", verbose_name=_('Name'))
214 2743e261 Kostas Papadimitriou
    status = tables.Column(accessor="state", verbose_name=_('Status'))
215 2743e261 Kostas Papadimitriou
216 2743e261 Kostas Papadimitriou
217 2743e261 Kostas Papadimitriou
    def render_name(self, value, record, *args, **kwargs):
218 5d87753f Kostas Papadimitriou
        return record.person.realname
219 2743e261 Kostas Papadimitriou
220 2743e261 Kostas Papadimitriou
    def render_status(self, value, *args, **kwargs):
221 2743e261 Kostas Papadimitriou
        return MEMBER_STATUS_DISPLAY.get(value, 'Unknown')
222 2743e261 Kostas Papadimitriou
223 2743e261 Kostas Papadimitriou
    class Meta:
224 2743e261 Kostas Papadimitriou
        template = "im/table_render.html"
225 2743e261 Kostas Papadimitriou
        model = ProjectMembership
226 2743e261 Kostas Papadimitriou
        fields = ('name', 'status')
227 2743e261 Kostas Papadimitriou
        attrs = {'id': 'members-table', 'class': 'members-table alt-style'}