Revision 9b32e2fb
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
1125 | 1125 |
""" |
1126 | 1126 |
Return projects accessed by specified user. |
1127 | 1127 |
""" |
1128 |
return self.filter(Q(owner=user) | Q(applicant=user) | \ |
|
1129 |
Q(project__projectmembership__person=user)).order_by('pk').distinct() |
|
1128 |
participates_fitlers = Q(owner=user) | Q(applicant=user) | \ |
|
1129 |
Q(project__projectmembership__person=user) |
|
1130 |
state_filters = (Q(state=ProjectApplication.PENDING) & \ |
|
1131 |
Q(precursor_application__isnull=True)) | \ |
|
1132 |
Q(state=ProjectApplication.APPROVED) |
|
1133 |
return self.filter(participates_fitlers & state_filters).order_by('issue_date').distinct() |
|
1130 | 1134 |
|
1131 | 1135 |
def search_by_name(self, *search_strings): |
1132 | 1136 |
q = Q() |
... | ... | |
1252 | 1256 |
except ProjectApplication.DoesNotExist: |
1253 | 1257 |
return |
1254 | 1258 |
|
1259 |
def followers(self): |
|
1260 |
current = self |
|
1261 |
try: |
|
1262 |
while current.projectapplication: |
|
1263 |
yield current.follower |
|
1264 |
current = current.follower |
|
1265 |
except: |
|
1266 |
pass |
|
1267 |
|
|
1268 |
def last_follower(self): |
|
1269 |
try: |
|
1270 |
return list(self.followers())[-1] |
|
1271 |
except IndexError: |
|
1272 |
return None |
|
1273 |
|
|
1255 | 1274 |
def submit(self, resource_policies, applicant, comments, |
1256 | 1275 |
precursor_application=None): |
1257 | 1276 |
|
b/snf-astakos-app/astakos/im/static/im/css/modules.css | ||
---|---|---|
557 | 557 |
-webkit-transition: width 1s, color 0.2s; /* Safari and Chrome */ |
558 | 558 |
-o-transition: width 1s, color 0.2s; /* Opera */ |
559 | 559 |
} |
560 |
|
|
561 |
i.tiny { font-size: 0.8em; color: #999;} |
b/snf-astakos-app/astakos/im/tables.py | ||
---|---|---|
37 | 37 |
from django.utils.safestring import mark_safe |
38 | 38 |
from django.template import Context, Template |
39 | 39 |
from django.template.loader import render_to_string |
40 |
from django.core.exceptions import PermissionDenied |
|
40 | 41 |
|
41 | 42 |
from django_tables2 import A |
42 | 43 |
import django_tables2 as tables |
43 | 44 |
|
44 | 45 |
from astakos.im.models import * |
45 | 46 |
from astakos.im.templatetags.filters import truncatename |
47 |
from astakos.im.functions import do_join_project_checks |
|
46 | 48 |
|
47 | 49 |
DEFAULT_DATE_FORMAT = "d/m/Y" |
48 | 50 |
|
49 | 51 |
|
50 |
MEMBER_STATUS_DISPLAY = { |
|
51 |
100: _('Owner'), |
|
52 |
0: _('Requested'), |
|
53 |
1: _('Pending'), |
|
54 |
2: _('Accepted'), |
|
55 |
3: _('Removing'), |
|
56 |
4: _('Removed'), |
|
57 |
-1: _('Unregistered'), |
|
58 |
} |
|
59 |
|
|
60 |
class TruncatedLinkColumn(tables.LinkColumn): |
|
52 |
class LinkColumn(tables.LinkColumn): |
|
61 | 53 |
|
62 | 54 |
def __init__(self, *args, **kwargs): |
63 |
self.truncate_chars = kwargs.pop('truncate_chars', 10) |
|
64 |
super(TruncatedLinkColumn, self).__init__(*args, **kwargs) |
|
65 |
|
|
55 |
self.coerce = kwargs.pop('coerce', None) |
|
56 |
self.append = kwargs.pop('append', None) |
|
57 |
super(LinkColumn, self).__init__(*args, **kwargs) |
|
58 |
|
|
59 |
def render(self, value, record, bound_column): |
|
60 |
link = super(LinkColumn, self).render(value, record, bound_column) |
|
61 |
extra = '' |
|
62 |
if self.append: |
|
63 |
if callable(self.append): |
|
64 |
extra = self.append(record, bound_column) |
|
65 |
else: |
|
66 |
extra = self.append |
|
67 |
return mark_safe(link + extra) |
|
66 | 68 |
|
67 | 69 |
def render_link(self, uri, text, attrs=None): |
68 |
text = truncatename(text, self.truncate_chars) |
|
69 |
return super(TruncatedLinkColumn, self).render_link(uri, text, attrs) |
|
70 |
if self.coerce: |
|
71 |
text = self.coerce(text) |
|
72 |
return super(LinkColumn, self).render_link(uri, text, attrs) |
|
70 | 73 |
|
71 | 74 |
|
72 | 75 |
# Helper columns |
... | ... | |
226 | 229 |
super(UserTable, self).__init__(*args, **kwargs) |
227 | 230 |
|
228 | 231 |
|
232 |
def project_name_append(record, column): |
|
233 |
try: |
|
234 |
if record.projectapplication and column.table.user.owns_project(record): |
|
235 |
if record.state == ProjectApplication.APPROVED: |
|
236 |
return mark_safe("<br /><i class='tiny'>%s</i>" % _('modifications pending')) |
|
237 |
else: |
|
238 |
return u'' |
|
239 |
else: |
|
240 |
return u'' |
|
241 |
except: |
|
242 |
return u'' |
|
243 |
|
|
229 | 244 |
# Table classes |
230 | 245 |
class UserProjectApplicationsTable(UserTable): |
231 | 246 |
caption = _('My projects') |
232 | 247 |
|
233 |
name = TruncatedLinkColumn('astakos.im.views.project_detail', |
|
234 |
truncate_chars=25, |
|
235 |
args=(A('pk'),)) |
|
236 |
issue_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT) |
|
248 |
name = LinkColumn('astakos.im.views.project_detail', |
|
249 |
coerce=lambda x: truncatename(x, 25), |
|
250 |
append=project_name_append, |
|
251 |
args=(A('pk'),)) |
|
252 |
issue_date = tables.DateColumn(verbose_name=_('Applied at'), format=DEFAULT_DATE_FORMAT) |
|
237 | 253 |
start_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT) |
238 |
end_date = tables.DateColumn(format=DEFAULT_DATE_FORMAT) |
|
239 |
members_count = tables.Column(verbose_name=_("Enrolled"), default=0,
|
|
254 |
end_date = tables.DateColumn(verbose_name=_('Expires at'), format=DEFAULT_DATE_FORMAT)
|
|
255 |
members_count = tables.Column(verbose_name=_("Members"), default=0,
|
|
240 | 256 |
sortable=False) |
241 | 257 |
membership_status = tables.Column(verbose_name=_("Status"), empty_values=(), |
242 | 258 |
sortable=False) |
... | ... | |
246 | 262 |
|
247 | 263 |
|
248 | 264 |
def render_membership_status(self, record, *args, **kwargs): |
249 |
status = record.user_status(self.user) |
|
250 |
if status == 100: |
|
251 |
return record.state |
|
265 |
if self.user.owns_project(record): |
|
266 |
return record.state_display() |
|
252 | 267 |
else: |
253 |
return MEMBER_STATUS_DISPLAY.get(status, 'Unknown') |
|
268 |
status = record.user_status(self.user) |
|
269 |
return record.user_status_display(self.user) |
|
254 | 270 |
|
255 | 271 |
class Meta: |
256 | 272 |
model = ProjectApplication |
257 |
fields = ('name', 'membership_status', 'issue_date', 'start_date','end_date', 'members_count')
|
|
273 |
fields = ('name', 'membership_status', 'issue_date', 'end_date', 'members_count') |
|
258 | 274 |
attrs = {'id': 'projects-list', 'class': 'my-projects alt-style'} |
259 | 275 |
template = "im/table_render.html" |
260 | 276 |
empty_text = _('No projects') |
261 | 277 |
|
278 |
class ProjectModificationApplicationsTable(UserProjectApplicationsTable): |
|
279 |
name = LinkColumn('astakos.im.views.project_detail', |
|
280 |
verbose_name=_('Action'), |
|
281 |
coerce= lambda x: 'review', |
|
282 |
args=(A('pk'),)) |
|
283 |
class Meta: |
|
284 |
attrs = {'id': 'projects-list', 'class': 'my-projects alt-style'} |
|
285 |
fields = ('issue_date', 'membership_status') |
|
286 |
exclude = ('start_date', 'end_date', 'members_count', 'project_action') |
|
262 | 287 |
|
263 | 288 |
def member_action_extra_context(membership, table, col): |
264 | 289 |
|
b/snf-astakos-app/astakos/im/templates/im/projects/project_detail.html | ||
---|---|---|
109 | 109 |
<dd>{% if object.limit_on_members_number%}{{object.limit_on_members_number}}{% else %} {% endif %}</dd> |
110 | 110 |
<dt>Member join policy</dt> |
111 | 111 |
<dd> |
112 |
{{ join_policies|lookup:object.member_join_policy }} |
|
112 |
{{ join_policies|lookup:object.member_join_policy|title }}
|
|
113 | 113 |
</dd> |
114 | 114 |
<dt>Member leave policy</dt> |
115 | 115 |
<dd> |
116 |
{{ leave_policies|lookup:object.member_leave_policy }} |
|
116 |
{{ leave_policies|lookup:object.member_leave_policy|title }}
|
|
117 | 117 |
</dd> |
118 | 118 |
</dl> |
119 | 119 |
</div> |
... | ... | |
170 | 170 |
</form> |
171 | 171 |
</div> |
172 | 172 |
{% endif %} |
173 |
{% comment %} |
|
174 |
{% if modifications_table %} |
|
175 |
<div class="full-dotted"> |
|
176 |
<h3>MODIFICATION REQUESTS</h3> |
|
177 |
{% render_table modifications_table %} |
|
178 |
</div> |
|
179 |
{% endif %} |
|
180 |
{% endcomment %} |
|
173 | 181 |
{% endif %} |
174 | 182 |
<div class="full-dotted"> |
175 | 183 |
<p> |
b/snf-astakos-app/astakos/im/views.py | ||
---|---|---|
1136 | 1136 |
prefix="members_") |
1137 | 1137 |
RequestConfig(request, paginate={"per_page": PAGINATE_BY}).configure(members_table) |
1138 | 1138 |
|
1139 |
modifications_table = None |
|
1140 |
if application.follower: |
|
1141 |
following_applications = list(application.followers()) |
|
1142 |
following_applications.reverse() |
|
1143 |
modifications_table = \ |
|
1144 |
tables.ProjectModificationApplicationsTable(following_applications, |
|
1145 |
user=request.user, |
|
1146 |
prefix="modifications_") |
|
1147 |
|
|
1139 | 1148 |
return object_detail( |
1140 | 1149 |
request, |
1141 | 1150 |
queryset=ProjectApplication.objects.select_related(), |
Also available in: Unified diff