| author | Alexandre Segura <mex.zktk@gmail.com> |
| Mon, 22 May 2017 11:39:26 +0200 | |
| changeset 515 | c1077e8f595d |
| parent 514 | accd1fded1a5 |
| child 521 | 63a7f61554fe |
| permissions | -rw-r--r-- |
| 298 | 1 |
from django.shortcuts import HttpResponse, get_object_or_404, render, redirect |
2 |
from django.http import Http404 |
|
3 |
from django.db.models import Count |
|
4 |
from django.contrib.auth.decorators import login_required |
|
5 |
from django.contrib.auth.models import User |
|
|
461
4701ee4556e3
Display message when revision needs approval.
Alexandre Segura <mex.zktk@gmail.com>
parents:
416
diff
changeset
|
6 |
from django.contrib import messages |
| 298 | 7 |
from django.views.generic import View, DetailView, RedirectView, TemplateView |
8 |
from django.views.generic.base import ContextMixin |
|
9 |
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
|
10 |
from django.core.urlresolvers import reverse |
|
11 |
from django.core.exceptions import ObjectDoesNotExist |
|
12 |
from django.contrib.contenttypes.models import ContentType |
|
13 |
from django.contrib.sites.models import Site |
|
14 |
from django.conf import settings |
|
15 |
from notifications.models import Notification |
|
| 514 | 16 |
from iconolab.models import Annotation, AnnotationRevision, Collection, Folder, Item, Image, IconolabComment, MetaCategory, MetaCategoryInfo, BookmarkCategory, Bookmark, Tag, TaggingInfo |
| 298 | 17 |
from iconolab.forms.annotations import AnnotationRevisionForm |
|
506
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
18 |
from iconolab.forms.bookmarks import BookmarkForm |
|
337
db6c41f04e79
Move serializers to dedicated file, do not create comment on revision creation.
Alexandre Segura <mex.zktk@gmail.com>
parents:
323
diff
changeset
|
19 |
from iconolab.serializers import AnnotationRevisionSerializer |
| 298 | 20 |
import logging |
21 |
||
22 |
logger = logging.getLogger(__name__) |
|
23 |
||
24 |
class GlobalHomepageView(View): |
|
25 |
""" |
|
26 |
View for the opening page of Iconolab. |
|
27 |
""" |
|
28 |
def get(self, request, *args, **kwargs): |
|
29 |
""" |
|
30 |
Template is iconolab/home.html |
|
31 |
||
32 |
Context variables provided to the template are: |
|
33 |
collections_primary: list of collections to display as big images |
|
34 |
collections_secondary: list of collections to display as small links at the bottom |
|
35 |
homepage = True: used to pass checks in the partials/header.html |
|
36 |
template to adjust the navbar to the homepage |
|
37 |
""" |
|
38 |
context = {} |
|
39 |
context['collections_primary'] = Collection.objects.filter(show_image_on_home=True).all() |
|
40 |
context['collections_secondary'] = Collection.objects.filter(show_image_on_home=False).all() |
|
| 514 | 41 |
context['latest_annotations'] = Annotation.objects.order_by("-created").all()[:5] |
42 |
||
43 |
# Best contributors |
|
44 |
count_contributions = Annotation.objects.all()\ |
|
45 |
.values('author').annotate(contributions=Count('author')).order_by('-contributions')[:10] |
|
46 |
best_contributors = [] |
|
47 |
for count_contribution in count_contributions: |
|
48 |
author = User.objects.get(id=count_contribution['author']) |
|
49 |
best_contributors.append({ |
|
50 |
'author': author, |
|
51 |
'contributions': count_contribution['contributions'] |
|
52 |
}) |
|
53 |
context['best_contributors'] = best_contributors |
|
54 |
||
55 |
# Most accurate tags (tags with accuracy >= 4) |
|
|
515
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
56 |
# SELECT ti.tag_id, ar.title, COUNT(DISTINCT(a.id)) AS cnt |
|
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
57 |
# FROM iconolab_tagginginfo ti |
|
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
58 |
# JOIN iconolab_annotationrevision ar ON ti.revision_id = ar.id |
|
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
59 |
# JOIN iconolab_annotation a ON ar.annotation_id = a.id |
|
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
60 |
# WHERE ti.accuracy >= 4 |
|
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
61 |
# GROUP BY ti.tag_id |
|
c1077e8f595d
Add search in tags only.
Alexandre Segura <mex.zktk@gmail.com>
parents:
514
diff
changeset
|
62 |
# ORDER BY cnt desc |
| 514 | 63 |
rows = TaggingInfo.objects\ |
64 |
.prefetch_related('revision', 'revision__annotation')\ |
|
65 |
.filter(accuracy__gte=4)\ |
|
66 |
.values('tag')\ |
|
67 |
.annotate(annotation_count=Count('revision__annotation', distinct=True))\ |
|
68 |
.order_by('-annotation_count')\ |
|
69 |
.all()[:10] |
|
70 |
||
71 |
most_accurate_tags = [] |
|
72 |
for row in rows: |
|
73 |
tag = Tag.objects.get(id=row['tag']) |
|
74 |
most_accurate_tags.append({ |
|
75 |
'tag': tag, |
|
76 |
'annotation_count': row['annotation_count'] |
|
77 |
}) |
|
78 |
context['most_accurate_tags'] = most_accurate_tags |
|
79 |
||
|
376
3d48f9520c8d
adds contact email as a setting variable from the app (instead of raw in the template
duong tam kien <tk@deveha.com>
parents:
343
diff
changeset
|
80 |
context['contact'] = settings.CONTACT_EMAIL |
| 298 | 81 |
context['homepage'] = True |
82 |
return render(request, 'iconolab/home.html', context) |
|
83 |
||
84 |
class TestView(View): |
|
85 |
template_name = 'iconolab/compare.html' |
|
86 |
||
87 |
def get(self, request, *args, **kwargs): |
|
88 |
return render(request, self.template_name) |
|
89 |
||
90 |
# Class with check_kwargs method to fetch objects from database depending on what level in the app we're currently at |
|
91 |
class IconolabObjectView(object): |
|
92 |
""" |
|
93 |
Superclass that defines method used in all object display views. |
|
94 |
""" |
|
95 |
def check_kwargs(self, kwargs): |
|
96 |
''' |
|
97 |
Returns a boolean depending on wether (True) or not (False) the objects |
|
98 |
were found and a tuple containing the objects, with a select_related/prefetch_related |
|
99 |
on relevant related objects following this ordering: |
|
100 |
(collection, item, image, annotation, revision) |
|
101 |
''' |
|
102 |
||
103 |
objects_tuple = () |
|
104 |
if 'collection_name' in kwargs.keys(): |
|
105 |
try: |
|
106 |
objects_tuple += (Collection.objects.prefetch_related('items', 'items__images').get(name=kwargs.get('collection_name')),) |
|
107 |
except (ValueError, Collection.DoesNotExist): |
|
108 |
return False, RedirectView.as_view(url=reverse('404error')) |
|
109 |
if 'item_guid' in kwargs.keys(): |
|
110 |
try: |
|
111 |
objects_tuple += (Item.objects.prefetch_related('images', 'metadatas', 'images__stats').get(item_guid=kwargs.get('item_guid')),) |
|
112 |
except (ValueError, Item.DoesNotExist): |
|
113 |
return False, RedirectView.as_view(url=reverse('404error')) |
|
114 |
if 'image_guid' in kwargs.keys(): |
|
115 |
try: |
|
116 |
objects_tuple += (Image.objects.prefetch_related('annotations', 'item', 'stats').get(image_guid=kwargs.get('image_guid')),) |
|
117 |
except (ValueError, Image.DoesNotExist): |
|
118 |
return False, RedirectView.as_view(url=reverse('404error')) |
|
119 |
if 'annotation_guid' in kwargs.keys(): |
|
120 |
try: |
|
121 |
objects_tuple += (Annotation.objects.prefetch_related('current_revision', 'stats', 'image').get(annotation_guid=kwargs.get('annotation_guid')),) |
|
122 |
except (ValueError, Annotation.DoesNotExist): |
|
123 |
return False, RedirectView.as_view(url=reverse('404error')) |
|
124 |
if 'revision_guid' in kwargs.keys(): |
|
125 |
try: |
|
126 |
objects_tuple += (AnnotationRevision.objects.prefetch_related('parent_revision').get(revision_guid=kwargs.get('revision_guid')),) |
|
127 |
except (ValueError, AnnotationRevision.DoesNotExist): |
|
128 |
return False, RedirectView.as_view(url=reverse('404error')) |
|
129 |
return True, objects_tuple |
|
130 |
||
131 |
def get_pagination_data(self, list_to_paginate, page, perpage, adjacent_pages_count, perpage_range=[5, 10, 25, 100], trailing_qarg=""): |
|
132 |
""" |
|
133 |
Takes a queryset or a list and returns a dict with pagination data for display purposes |
|
134 |
||
135 |
Dict will be of the format: |
|
136 |
{ |
|
137 |
page: the page to load (integer) |
|
138 |
perpage_range: a list of the page links to display (list of integers) |
|
139 |
perpage: the item count per page (integer) |
|
140 |
perpage_range: a list of the perpage values to display next to the page list (list of integers) |
|
141 |
trailing_qarg: optional trailing qarg for the paginations links (used in collection home to remember the state of each list between page loads) (string) |
|
142 |
list: the item list to display (list of objects) |
|
143 |
show_first: used in template to display links, will be True if 1 is not in page_range |
|
144 |
show_last: used in template to display links, will be True if page_count is not in page_range |
|
145 |
ellipsis_first: used in template to display links, will be True if page_range starts at 3 or more |
|
146 |
ellipsis_last: used in template to display links, will be True if page_range ends at last_page - 2 or less |
|
147 |
||
148 |
} |
|
149 |
""" |
|
150 |
pagination_data = {} |
|
151 |
pagination_data["page"] = page |
|
152 |
pagination_data["perpage"] = perpage |
|
153 |
pagination_data["perpage_range"] = perpage_range |
|
154 |
pagination_data["trailing_qarg"] = trailing_qarg |
|
155 |
paginator = Paginator(list_to_paginate, perpage) |
|
156 |
try: |
|
157 |
pagination_data["list"] = paginator.page(page) |
|
158 |
except PageNotAnInteger: |
|
159 |
pagination_data["list"] = paginator.page(1) |
|
160 |
except EmptyPage: |
|
161 |
pagination_data["list"] = paginator.page(paginator.num_pages) |
|
162 |
pagination_data["page_range"] = [ |
|
163 |
n for n in \ |
|
164 |
range(page - adjacent_pages_count, page + adjacent_pages_count + 1) \ |
|
165 |
if n > 0 and n <= paginator.num_pages |
|
166 |
] |
|
167 |
pagination_data["show_first"] = page - adjacent_pages_count > 1 |
|
168 |
pagination_data["ellipsis_first"] = pagination_data["show_first"] and (page - adjacent_pages_count != 2) |
|
169 |
pagination_data["show_last"] = page + adjacent_pages_count < paginator.num_pages |
|
170 |
pagination_data["ellipsis_last"] = pagination_data["show_last"] and (page + adjacent_pages_count != paginator.num_pages - 1) |
|
171 |
return pagination_data |
|
172 |
||
173 |
class CollectionHomepageView(View, ContextMixin, IconolabObjectView): |
|
174 |
""" |
|
175 |
View that displays a collection and four panels to show relevant paginated lists for collection: |
|
176 |
* item lists |
|
177 |
* annotations ordered by creation date |
|
178 |
* annotations ordered by revisions count |
|
179 |
* annotations where a metacategory that notifies contributors was called |
|
180 |
""" |
|
181 |
def get(self, request, *args, **kwargs): |
|
182 |
""" |
|
183 |
Template is iconolab/collection_home.html |
|
184 |
||
185 |
Url args are: |
|
186 |
- collection_name: 'name' attribute of the requested collection |
|
187 |
||
188 |
Queryargs understood by the view are: |
|
189 |
- show : panel that will be shown on page load, one of ['items', 'recent', 'revised', 'contributions'], default to "items" |
|
190 |
- items_page : item list page to load |
|
191 |
- items_perpage : item count per page |
|
192 |
- recent_page : recent annotations list page to load |
|
193 |
- recent_perpage : recent annotations count per page |
|
194 |
- revised_page : most revised annotations list page to load |
|
195 |
- revised_perpage : most revised annotations count per page |
|
196 |
- contributions_page : annotations with the most contribution calls list page to load |
|
197 |
- contributions_perpage : annotations with the most contribution calls count per page for item list |
|
198 |
||
199 |
Context variables provided to the template are: |
|
200 |
- collection: the collection object for the requested collection |
|
201 |
- collection_name : the collection_name url arg |
|
202 |
- items_pagination_data: pagination data dict in the format of the IconolabObjectView.get_pagination_data() method for the items list |
|
203 |
- recent_pagination_data: pagination data dict in the format of the IconolabObjectView.get_pagination_data() method for the recent annotations list |
|
204 |
- revised_pagination_data: pagination data dict in the format of the IconolabObjectView.get_pagination_data() method for the revised annotations list |
|
205 |
- contributions_pagination_data: pagination data dict in the format of the IconolabObjectView.get_pagination_data() method for the contribution calls annotations list |
|
206 |
""" |
|
207 |
||
208 |
success, result = self.check_kwargs(kwargs) |
|
209 |
if success: |
|
210 |
(collection,) = result |
|
211 |
else: |
|
212 |
return result(request) |
|
213 |
context = super(CollectionHomepageView, self).get_context_data(**kwargs) |
|
214 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
215 |
context['collection'] = collection |
|
216 |
||
217 |
# get Pagination and navigation query args |
|
218 |
try: |
|
219 |
items_page = int(request.GET.get('items_page', '1')) |
|
220 |
except ValueError: |
|
221 |
items_page = 1 |
|
222 |
try: |
|
223 |
items_per_page = int(request.GET.get('items_perpage', '12')) |
|
224 |
except ValueError: |
|
225 |
items_per_page = 12 |
|
226 |
||
227 |
try: |
|
228 |
recent_page = int(request.GET.get('recent_page', '1')) |
|
229 |
except ValueError: |
|
230 |
recent_page = 1 |
|
231 |
try: |
|
232 |
recent_per_page = int(request.GET.get('recent_perpage', '10')) |
|
233 |
except ValueError: |
|
234 |
recent_per_page = 10 |
|
235 |
||
236 |
try: |
|
237 |
revised_page = int(request.GET.get('revised_page', '1')) |
|
238 |
except ValueError: |
|
239 |
revised_page = 1 |
|
240 |
try: |
|
241 |
revised_per_page = int(request.GET.get('revised_perpage', '10')) |
|
242 |
except ValueError: |
|
243 |
revised_per_page = 10 |
|
244 |
||
245 |
try: |
|
246 |
contributions_page = int(request.GET.get('contributions_page', '1')) |
|
247 |
except ValueError: |
|
248 |
contributions_page = 1 |
|
249 |
try: |
|
250 |
contributions_per_page = int(request.GET.get('contributions_perpage', '10')) |
|
251 |
except ValueError: |
|
252 |
contributions_per_page = 10 |
|
253 |
||
254 |
active_list = request.GET.get('show', 'items') |
|
255 |
if active_list not in ['items', 'recent', 'revised', 'contributions']: |
|
256 |
active_list = 'items' |
|
257 |
context["active_list"] = active_list |
|
258 |
||
259 |
||
260 |
# Pagination values |
|
261 |
adjacent_pages_count = 2 |
|
262 |
||
263 |
# Paginated objects list |
|
| 416 | 264 |
items_list = collection.items.order_by("metadatas__inventory_number") |
265 |
||
266 |
folder = request.GET.get('folder', None) |
|
267 |
||
268 |
if folder is not None: |
|
|
467
5d0879ffa7de
Use folder GUID instead of primary key.
Alexandre Segura <mex.zktk@gmail.com>
parents:
465
diff
changeset
|
269 |
items_list = items_list.filter(folders__folder_guid=folder) |
|
486
869bb212631a
Add link to show selected folder below collection title.
Alexandre Segura <mex.zktk@gmail.com>
parents:
482
diff
changeset
|
270 |
context['folder_name'] = Folder.objects.get(folder_guid=folder).name |
| 416 | 271 |
|
|
467
5d0879ffa7de
Use folder GUID instead of primary key.
Alexandre Segura <mex.zktk@gmail.com>
parents:
465
diff
changeset
|
272 |
context['folder_guid'] = folder |
| 416 | 273 |
|
| 491 | 274 |
items_pagination_args = '&'.join([ |
275 |
"recent_page="+str(recent_page), |
|
276 |
"recent_perpage="+str(recent_per_page), |
|
277 |
"revised_page="+str(revised_page), |
|
278 |
"revised_perpage="+str(revised_per_page), |
|
279 |
"contributions_page="+str(contributions_page), |
|
280 |
"contributions_perpage="+str(contributions_per_page) |
|
281 |
]) |
|
282 |
||
283 |
if folder is not None: |
|
284 |
items_pagination_args += "&folder=" + folder |
|
285 |
||
| 298 | 286 |
context["items_pagination_data"] = self.get_pagination_data( |
| 416 | 287 |
items_list.all(), |
| 298 | 288 |
items_page, |
289 |
items_per_page, |
|
290 |
adjacent_pages_count, |
|
291 |
perpage_range=[6, 12, 48, 192], |
|
| 491 | 292 |
trailing_qarg=items_pagination_args |
| 298 | 293 |
) |
294 |
||
295 |
# Paginated recent annotations list |
|
296 |
recent_annotations = Annotation.objects.filter(image__item__collection__name=collection.name).prefetch_related( |
|
297 |
'current_revision', |
|
298 |
'stats' |
|
299 |
).order_by('-current_revision__created') |
|
300 |
context["recent_pagination_data"] = self.get_pagination_data( |
|
301 |
recent_annotations, |
|
302 |
recent_page, |
|
303 |
recent_per_page, |
|
304 |
adjacent_pages_count, |
|
305 |
trailing_qarg="&items_page="+str(items_page) |
|
306 |
+"&items_perpage="+str(items_per_page) |
|
307 |
+"&revised_page="+str(revised_page) |
|
308 |
+"&revised_perpage="+str(revised_per_page) |
|
309 |
+"&contributions_page="+str(contributions_page) |
|
310 |
+"&contributions_perpage="+str(contributions_per_page) |
|
311 |
) |
|
312 |
||
313 |
# Paginated revised annotations list |
|
314 |
revised_annotations = Annotation.objects.filter(image__item__collection__name=collection.name).prefetch_related( |
|
315 |
'current_revision', |
|
316 |
'stats' |
|
317 |
).annotate(revision_count=Count('revisions')).order_by('-revision_count') |
|
318 |
context["revised_pagination_data"] = self.get_pagination_data( |
|
319 |
revised_annotations, |
|
320 |
revised_page, |
|
321 |
revised_per_page, |
|
322 |
adjacent_pages_count, |
|
323 |
trailing_qarg="&items_page="+str(items_page) |
|
324 |
+"&items_perpage="+str(items_per_page) |
|
325 |
+"&recent_page="+str(recent_page) |
|
326 |
+"&recent_perpage="+str(recent_per_page) |
|
327 |
+"&contributions_page="+str(contributions_page) |
|
328 |
+"&contributions_perpage="+str(contributions_per_page) |
|
329 |
) |
|
330 |
||
331 |
# Paginated contribution calls annotation list |
|
332 |
contrib_calls_annotations_ids = list(set(MetaCategoryInfo.objects.filter( |
|
333 |
metacategory__collection__name=collection.name, |
|
334 |
metacategory__triggers_notifications=MetaCategory.CONTRIBUTORS |
|
335 |
).order_by('comment__submit_date').values_list('comment__object_pk', flat=True))) |
|
336 |
collection_annotations = Annotation.objects.filter(id__in=contrib_calls_annotations_ids).all() |
|
337 |
collection_ann_dict = dict([(str(annotation.id), annotation) for annotation in collection_annotations]) |
|
338 |
contributions_annotations = [collection_ann_dict[id] for id in contrib_calls_annotations_ids] |
|
339 |
context["contributions_pagination_data"] = self.get_pagination_data( |
|
340 |
contributions_annotations, |
|
341 |
contributions_page, |
|
342 |
contributions_per_page, |
|
343 |
adjacent_pages_count, |
|
344 |
trailing_qarg="&items_page="+str(items_page) |
|
345 |
+"&items_perpage="+str(items_per_page) |
|
346 |
+"&recent_page="+str(recent_page) |
|
347 |
+"&recent_perpage="+str(recent_per_page) |
|
348 |
+"&revised_page="+str(revised_page) |
|
349 |
+"&revised_perpage="+str(revised_per_page) |
|
350 |
) |
|
351 |
||
|
506
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
352 |
context['bookmark_form'] = BookmarkForm(user=request.user) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
353 |
|
| 298 | 354 |
return render(request, 'iconolab/collection_home.html', context) |
355 |
||
356 |
||
357 |
||
358 |
class ShowItemView(View, ContextMixin, IconolabObjectView): |
|
359 |
""" |
|
360 |
View that displays informations on an item with associated metadatas and stats. Also displays images and annotation list for each image. |
|
361 |
""" |
|
362 |
def get(self, request, *args, **kwargs): |
|
363 |
""" |
|
364 |
Template is iconolab/item_detail.html |
|
365 |
||
366 |
Url args are: |
|
367 |
- collection_name : name of the collection |
|
368 |
- item_guid: 'item_guid' attribute of the requested item |
|
369 |
||
370 |
Queryargs understood by the view are: |
|
371 |
- show: image_guid for the image to show on load |
|
372 |
- page: annotation list page on load for displayed image |
|
373 |
- perpage: annotation count per page on load for displayed image |
|
374 |
||
375 |
Context variables provided to the template are: |
|
376 |
- collection_name : the collection_name url arg |
|
377 |
- item_guid: the item_guid url arg |
|
378 |
- collection: the collection object for the requested collection |
|
379 |
- item: the item object for the requested item |
|
380 |
- display_image: the image_guid for the image to display on load |
|
381 |
- images: a list of dict for the item images data in the format: |
|
382 |
{ |
|
383 |
'obj': the image object, |
|
384 |
'annotations': the list of annotations on that image |
|
385 |
} |
|
386 |
""" |
|
387 |
||
388 |
success, result = self.check_kwargs(kwargs) |
|
|
323
55c024fc7c60
Roughly implement annotation navigator.
Alexandre Segura <mex.zktk@gmail.com>
parents:
298
diff
changeset
|
389 |
|
| 298 | 390 |
if success: |
391 |
(collection, item) = result |
|
392 |
else: |
|
393 |
return result(request) |
|
394 |
||
395 |
context = super(ShowItemView, self).get_context_data(**kwargs) |
|
396 |
image_guid_to_display = request.GET.get("show", str(item.images.first().image_guid)) |
|
397 |
if image_guid_to_display not in [str(guid) for guid in item.images.all().values_list("image_guid", flat=True)]: |
|
398 |
image_guid_to_display = str(item.images.first().image_guid) |
|
399 |
context['display_image'] = image_guid_to_display |
|
400 |
try: |
|
401 |
displayed_annotations_page = int(request.GET.get('page', '1')) |
|
402 |
except ValueError: |
|
403 |
displayed_annotations_page = 1 |
|
404 |
try: |
|
405 |
displayed_annotations_per_page = int(request.GET.get('perpage', '10')) |
|
406 |
except ValueError: |
|
407 |
displayed_annotations_per_page = 10 |
|
408 |
||
409 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
410 |
context['item_guid'] = self.kwargs.get('image_guid', '') |
|
411 |
context['collection'] = collection |
|
412 |
context['item'] = item |
|
413 |
context['images'] = [] |
|
414 |
for image in item.images.all(): |
|
415 |
if str(image.image_guid) == image_guid_to_display: |
|
416 |
page = displayed_annotations_page |
|
417 |
per_page = displayed_annotations_per_page |
|
418 |
else: |
|
419 |
page = 1 |
|
420 |
per_page = 10 |
|
421 |
annotations_paginator = Paginator(image.annotations.all(), per_page) |
|
422 |
try: |
|
423 |
annotations = annotations_paginator.page(page) |
|
424 |
except PageNotAnInteger: |
|
425 |
annotations = annotations_paginator.page(1) |
|
426 |
except EmptyPage: |
|
427 |
annotations = annotations_paginator.page(recent_paginator.num_pages) |
|
428 |
context['images'].append({ |
|
429 |
'obj' : image, |
|
430 |
'annotations': annotations |
|
431 |
}) |
|
432 |
image.stats.views_count += 1 |
|
433 |
image.stats.save() |
|
434 |
return render(request, 'iconolab/detail_item.html', context); |
|
435 |
||
436 |
class ShowImageView(View, ContextMixin, IconolabObjectView): |
|
437 |
""" |
|
438 |
View that only displays an image and the associated annotations |
|
439 |
""" |
|
440 |
def get(self, request, *args, **kwargs): |
|
441 |
success, result = self.check_kwargs(kwargs) |
|
442 |
if success: |
|
443 |
(collection, image) = result |
|
444 |
else: |
|
445 |
return result(request) |
|
446 |
context = super(ShowImageView, self).get_context_data(**kwargs) |
|
447 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
448 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
449 |
context['collection'] = collection |
|
450 |
context['image'] = image |
|
|
407
74e0a5ea614a
Display item metadata below image.
Alexandre Segura <mex.zktk@gmail.com>
parents:
376
diff
changeset
|
451 |
context['item'] = image.item |
|
323
55c024fc7c60
Roughly implement annotation navigator.
Alexandre Segura <mex.zktk@gmail.com>
parents:
298
diff
changeset
|
452 |
context['form'] = AnnotationRevisionForm() |
| 298 | 453 |
return render(request, 'iconolab/detail_image.html', context) |
454 |
||
|
506
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
455 |
class BookmarkImageView(View, ContextMixin, IconolabObjectView): |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
456 |
def post(self, request, *args, **kwargs): |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
457 |
success, result = self.check_kwargs(kwargs) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
458 |
if success: |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
459 |
(collection, image) = result |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
460 |
else: |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
461 |
return result(request) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
462 |
|
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
463 |
context = super(BookmarkImageView, self).get_context_data(**kwargs) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
464 |
|
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
465 |
bookmark_form = BookmarkForm(request.POST, user=request.user) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
466 |
if bookmark_form.is_valid(): |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
467 |
bookmark = Bookmark( |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
468 |
image=image, |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
469 |
category=bookmark_form.cleaned_data['category'] |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
470 |
) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
471 |
bookmark.save() |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
472 |
|
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
473 |
context['bookmark_form'] = bookmark_form |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
474 |
|
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
475 |
redirect_url = reverse('collection_home', kwargs={'collection_name': self.kwargs.get('collection_name', '')}) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
476 |
|
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
477 |
return redirect(redirect_url) |
|
4e18e1f69db9
Introduce bookmarks feature.
Alexandre Segura <mex.zktk@gmail.com>
parents:
491
diff
changeset
|
478 |
|
| 298 | 479 |
class CreateAnnotationView(View, ContextMixin, IconolabObjectView): |
480 |
""" |
|
481 |
View that displays annotation forms and handles annotation creation |
|
482 |
""" |
|
483 |
def get_context_data(self, **kwargs): |
|
484 |
context = super(CreateAnnotationView, self).get_context_data(**kwargs) |
|
485 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
486 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
487 |
return context |
|
488 |
||
489 |
def get(self, request, *args, **kwargs): |
|
490 |
success, result = self.check_kwargs(kwargs) |
|
491 |
if success: |
|
492 |
(collection, image,) = result |
|
493 |
else: |
|
494 |
return result(request) |
|
495 |
annotation_form = AnnotationRevisionForm() |
|
496 |
context = self.get_context_data(**kwargs) |
|
497 |
context['image'] = image |
|
498 |
context['form'] = annotation_form |
|
499 |
context['tags_data'] = '[]' |
|
500 |
return render(request, 'iconolab/change_annotation.html', context) |
|
501 |
||
502 |
def post(self, request, *args, **kwargs): |
|
503 |
success, result = self.check_kwargs(kwargs) |
|
504 |
if success: |
|
505 |
(collection, image) = result |
|
506 |
else: |
|
507 |
return result(request) |
|
508 |
collection_name = kwargs['collection_name'] |
|
509 |
image_guid = kwargs['image_guid'] |
|
510 |
annotation_form = AnnotationRevisionForm(request.POST) |
|
511 |
if annotation_form.is_valid(): |
|
512 |
author = request.user |
|
513 |
title = annotation_form.cleaned_data['title'] |
|
514 |
description = annotation_form.cleaned_data['description'] |
|
515 |
fragment = annotation_form.cleaned_data['fragment'] |
|
516 |
tags_json = annotation_form.cleaned_data['tags'] |
|
517 |
new_annotation = Annotation.objects.create_annotation(author, image, title=title, description=description, fragment=fragment, tags_json=tags_json) |
|
|
323
55c024fc7c60
Roughly implement annotation navigator.
Alexandre Segura <mex.zktk@gmail.com>
parents:
298
diff
changeset
|
518 |
redirect_url = reverse('image_detail', kwargs={'collection_name': collection_name, 'image_guid': image_guid}) |
|
343
6f901f3b1510
Redirect to annotation using hash.
Alexandre Segura <mex.zktk@gmail.com>
parents:
337
diff
changeset
|
519 |
return redirect(redirect_url + '#' + str(new_annotation.annotation_guid)) |
| 298 | 520 |
context = self.get_context_data(**kwargs) |
521 |
context['image'] = image |
|
522 |
context['form'] = annotation_form |
|
523 |
context['tags_data'] = '[]' |
|
524 |
return render(request, 'iconolab/change_annotation.html', context) |
|
525 |
||
526 |
class ShowAnnotationView(View, ContextMixin, IconolabObjectView): |
|
|
470
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
527 |
def get(self, request, *args, **kwargs): |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
528 |
success, result = self.check_kwargs(kwargs) |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
529 |
if success: |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
530 |
(collection, image, annotation) = result |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
531 |
else: |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
532 |
return result(request) |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
533 |
context = super(ShowAnnotationView, self).get_context_data(**kwargs) |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
534 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
535 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
536 |
context['collection'] = collection |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
537 |
context['image'] = image |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
538 |
context['item'] = image.item |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
539 |
context['annotation'] = annotation |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
540 |
context['form'] = AnnotationRevisionForm() |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
541 |
return render(request, 'iconolab/detail_image.html', context) |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
542 |
|
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
543 |
class ShowAnnotationViewOld(View, ContextMixin, IconolabObjectView): |
| 298 | 544 |
""" |
545 |
View that show a given annotation with the corresponding data, links to |
|
546 |
submit new revisions and the paginated comments thread. |
|
547 |
""" |
|
548 |
||
549 |
||
550 |
def get_context_data(self, **kwargs): |
|
| 479 | 551 |
context = super(ShowAnnotationViewOld, self).get_context_data(**kwargs) |
| 298 | 552 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
553 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
554 |
context['annotation_guid'] = self.kwargs.get('annotation_guid', '') |
|
555 |
return context |
|
556 |
||
557 |
def get(self, request, *args, **kwargs): |
|
558 |
""" |
|
559 |
Template is iconolab/detail_annotations.html |
|
560 |
||
561 |
Url args are: |
|
562 |
- collection_name: 'name' attribute of the requested collection |
|
563 |
- item_guid: 'item_guid' attribute of the requested item |
|
564 |
- annotation_guid: 'annotation_guid' attribute of the requested annotation |
|
565 |
||
566 |
Queryargs understood by the view are: |
|
567 |
- page: comment thread page on load |
|
568 |
- perpage: comment count per page on load |
|
569 |
||
570 |
Context variables provided to the template are: |
|
571 |
- collection: the collection object for the requested collection |
|
572 |
- image: the image object for the requested image |
|
573 |
- annotation: the annotation object for the requested annotation |
|
574 |
- tags_data: a json string describing tags for the annotation current revision |
|
575 |
- comments: the paginated comments list for the annotation according page and perpage queryargs |
|
576 |
- notification_comments_ids: the ids of the comments that are referenced by a notification for the authenticated user; This allows |
|
577 |
us to highlight comments that triggered a notification in the page |
|
578 |
""" |
|
579 |
success, result = self.check_kwargs(kwargs) |
|
580 |
if success: |
|
581 |
(collection, image, annotation,) = result |
|
582 |
else: |
|
583 |
return result(request) |
|
584 |
context = self.get_context_data(**kwargs) |
|
585 |
context['collection'] = collection |
|
586 |
context['image'] = image |
|
587 |
context['annotation'] = annotation |
|
588 |
context['tags_data'] = annotation.current_revision.get_tags_json() |
|
589 |
||
590 |
page = request.GET.get('page', 1) |
|
591 |
per_page = request.GET.get('perpage', 10) |
|
592 |
full_comments_list = IconolabComment.objects.for_app_models('iconolab.annotation').filter(object_pk = annotation.pk).order_by('thread_id', '-order') |
|
593 |
paginator = Paginator(full_comments_list, per_page) |
|
594 |
try: |
|
595 |
comments_list = paginator.page(page) |
|
596 |
except PageNotAnInteger: |
|
597 |
comments_list = paginator.page(1) |
|
598 |
except EmptyPage: |
|
599 |
comments_list = paginator.page(paginator.num_pages) |
|
600 |
context['comments'] = comments_list |
|
601 |
||
602 |
if request.user.is_authenticated(): |
|
603 |
user_comment_notifications = Notification.objects.filter( |
|
604 |
recipient=request.user, |
|
605 |
action_object_content_type__app_label='iconolab', |
|
606 |
action_object_content_type__model='iconolabcomment', |
|
607 |
target_content_type__app_label='iconolab', |
|
608 |
target_content_type__model='annotation', |
|
609 |
target_object_id=annotation.id |
|
610 |
).unread() |
|
611 |
context['notifications_comments_ids'] = [int(val) for val in user_comment_notifications.values_list('action_object_object_id', flat=True)] |
|
612 |
comment_list_ids = [comment.id for comment in context['comments'] ] |
|
613 |
for notification in user_comment_notifications.all(): |
|
614 |
if int(notification.action_object_object_id) in comment_list_ids: |
|
615 |
notification.mark_as_read() |
|
616 |
||
617 |
image.stats.views_count += 1 |
|
618 |
image.stats.save() |
|
619 |
annotation.stats.views_count += 1 |
|
620 |
annotation.stats.save() |
|
621 |
return render(request, 'iconolab/detail_annotation.html', context) |
|
622 |
||
|
482
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
623 |
class ShowRevisionsView(View, ContextMixin, IconolabObjectView): |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
624 |
def get_context_data(self, **kwargs): |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
625 |
context = super(ShowRevisionsView, self).get_context_data(**kwargs) |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
626 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
627 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
628 |
context['annotation_guid'] = self.kwargs.get('annotation_guid', '') |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
629 |
return context |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
630 |
|
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
631 |
def get(self, request, *args, **kwargs): |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
632 |
success, result = self.check_kwargs(kwargs) |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
633 |
if success: |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
634 |
(collection, image, annotation,) = result |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
635 |
else: |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
636 |
return result(request) |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
637 |
|
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
638 |
context = self.get_context_data(**kwargs) |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
639 |
context['collection'] = collection |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
640 |
context['image'] = image |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
641 |
context['annotation'] = annotation |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
642 |
|
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
643 |
context['revisions'] = AnnotationRevision.objects.filter(annotation=annotation).order_by('-created') |
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
644 |
|
|
b71475c27159
Add page with list of revisions.
Alexandre Segura <mex.zktk@gmail.com>
parents:
479
diff
changeset
|
645 |
return render(request, 'iconolab/annotation_revisions.html', context) |
| 298 | 646 |
|
647 |
class ReadonlyAnnotationView(View, ContextMixin, IconolabObjectView): |
|
648 |
""" |
|
649 |
Same view as ShowAnnotationView but without the comments and links to the forms |
|
650 |
""" |
|
651 |
def get_context_data(self, **kwargs): |
|
652 |
context = super(ReadonlyAnnotationView, self).get_context_data(**kwargs) |
|
653 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
654 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
655 |
context['annotation_guid'] = self.kwargs.get('annotation_guid', '') |
|
656 |
return context |
|
657 |
||
658 |
def get(self, request, *args, **kwargs): |
|
659 |
""" |
|
660 |
Exactly the same as ShowAnnotationView but without all the data around comments |
|
661 |
""" |
|
662 |
success, result = self.check_kwargs(kwargs) |
|
663 |
if success: |
|
664 |
(collection, image, annotation,) = result |
|
665 |
else: |
|
666 |
return result(request) |
|
667 |
context = self.get_context_data(**kwargs) |
|
668 |
context['collection'] = collection |
|
669 |
context['image'] = image |
|
670 |
context['annotation'] = annotation |
|
671 |
context['tags_data'] = annotation.current_revision.get_tags_json() |
|
672 |
||
673 |
image.stats.views_count += 1 |
|
674 |
image.stats.save() |
|
675 |
annotation.stats.views_count += 1 |
|
676 |
annotation.stats.save() |
|
677 |
return render(request, 'iconolab/detail_annotation_readonly.html', context) |
|
678 |
||
679 |
class EditAnnotationView(View, ContextMixin, IconolabObjectView): |
|
680 |
""" |
|
681 |
View that handles displaying the edition form and editing an annotation |
|
682 |
""" |
|
683 |
def get_context_data(self, **kwargs): |
|
684 |
context = super(EditAnnotationView, self).get_context_data(**kwargs) |
|
685 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
686 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
687 |
context['annotation_guid'] = self.kwargs.get('annotation_guid', '') |
|
688 |
return context |
|
689 |
||
690 |
def get(self, request, *args, **kwargs): |
|
691 |
success, result = self.check_kwargs(kwargs) |
|
692 |
if success: |
|
693 |
(collection, image, annotation,) = result |
|
694 |
else: |
|
695 |
return result(request) |
|
696 |
annotation_form = AnnotationRevisionForm(instance=annotation.current_revision) |
|
697 |
context = self.get_context_data(**kwargs) |
|
698 |
context['image'] = image |
|
699 |
context['annotation'] = annotation |
|
700 |
context['form'] = annotation_form |
|
701 |
context['tags_data'] = annotation.current_revision.get_tags_json() |
|
702 |
return render(request, 'iconolab/change_annotation.html', context) |
|
703 |
||
704 |
def post(self, request, *args, **kwargs): |
|
705 |
success, result = self.check_kwargs(kwargs) |
|
706 |
if success: |
|
707 |
(collection, image, annotation) = result |
|
708 |
else: |
|
709 |
return result(request) |
|
710 |
collection_name = kwargs['collection_name'] |
|
711 |
image_guid = kwargs['image_guid'] |
|
712 |
annotation_guid = kwargs['annotation_guid'] |
|
713 |
annotation_form = AnnotationRevisionForm(request.POST) |
|
714 |
if annotation_form.is_valid(): |
|
715 |
revision_author = request.user |
|
716 |
revision_title = annotation_form.cleaned_data['title'] |
|
717 |
revision_description = annotation_form.cleaned_data['description'] |
|
718 |
revision_fragment = annotation_form.cleaned_data['fragment'] |
|
719 |
revision_tags_json = annotation_form.cleaned_data['tags'] |
|
720 |
new_revision = annotation.make_new_revision(revision_author, revision_title, revision_description, revision_fragment, revision_tags_json) |
|
|
461
4701ee4556e3
Display message when revision needs approval.
Alexandre Segura <mex.zktk@gmail.com>
parents:
416
diff
changeset
|
721 |
|
|
4701ee4556e3
Display message when revision needs approval.
Alexandre Segura <mex.zktk@gmail.com>
parents:
416
diff
changeset
|
722 |
if (annotation.author != revision_author): |
| 465 | 723 |
messages.add_message(request, messages.INFO, "Votre modification a été prise en compte. Le créateur de l'annotation a été notifié.") |
|
461
4701ee4556e3
Display message when revision needs approval.
Alexandre Segura <mex.zktk@gmail.com>
parents:
416
diff
changeset
|
724 |
|
|
470
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
725 |
redirect_url = reverse('annotation_detail', kwargs={'collection_name': collection_name, 'image_guid': image_guid, 'annotation_guid': str(annotation.annotation_guid)}) |
|
6c43539e5c67
Use browser history instead of hash for annotation URL.
Alexandre Segura <mex.zktk@gmail.com>
parents:
467
diff
changeset
|
726 |
return redirect(redirect_url) |
| 298 | 727 |
context = self.get_context_data(**kwargs) |
728 |
context['image'] = image |
|
729 |
context['form'] = annotation_form |
|
730 |
context['annotation'] = annotation |
|
731 |
context['tags_data'] = annotation.current_revision.get_tags_json() |
|
732 |
return render(request, 'iconolab/change_annotation.html', context) |
|
733 |
||
734 |
||
735 |
class ShowRevisionView(View, ContextMixin, IconolabObjectView): |
|
736 |
""" |
|
737 |
View that displays a given revision with its associated data and comment |
|
738 |
""" |
|
739 |
def get_context_data(self, **kwargs): |
|
740 |
context = super(ShowRevisionView, self).get_context_data(**kwargs) |
|
741 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
742 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
743 |
context['annotation_guid'] = self.kwargs.get('annotation_guid', '') |
|
744 |
context['revision_guid'] = self.kwargs.get('revision_guid', '') |
|
745 |
return context |
|
746 |
||
747 |
def get(self, request, *args, **kwargs): |
|
748 |
""" |
|
749 |
Template is iconolab/detail_annotations.html |
|
750 |
||
751 |
Url args are: |
|
752 |
- collection_name: 'name' attribute of the requested collection |
|
753 |
- item_guid: 'item_guid' attribute of the requested item |
|
754 |
- annotation_guid: 'annotation_guid' attribute of the requested annotation |
|
755 |
- revision_guid: 'revision_guid' attribute of the requested revision |
|
756 |
||
757 |
Context variables provided to the template are: |
|
758 |
- collection: the collection object for the requested collection |
|
759 |
- image: the image object for the requested image |
|
760 |
- annotation: the annotation object for the requested annotation |
|
761 |
- revision: the revision object for the requested annotation |
|
762 |
- tags_data: a json string describing tags for the annotation current revision |
|
763 |
- comment: the comment that was posted alongside the revision |
|
764 |
- notified_revision: if True, the revision is linked from one or more unread notifications for the |
|
765 |
current user, allowing us to highlight it in the template. |
|
766 |
""" |
|
767 |
success, result = self.check_kwargs(kwargs) |
|
768 |
if success: |
|
769 |
(collection, image, annotation, revision,) = result |
|
770 |
else: |
|
771 |
return result(request) |
|
772 |
context = self.get_context_data(**kwargs) |
|
773 |
context['collection'] = collection |
|
774 |
context['image'] = image |
|
775 |
context['annotation'] = annotation |
|
776 |
context['revision'] = revision |
|
777 |
context['tags_data'] = revision.get_tags_json() |
|
778 |
context['comment'] = revision.creation_comment.first() |
|
779 |
if request.user.is_authenticated() and annotation.author == request.user: |
|
780 |
ann_author_notified = Notification.objects.filter( |
|
781 |
recipient=request.user, |
|
782 |
action_object_content_type__app_label='iconolab', |
|
783 |
action_object_content_type__model='annotationrevision', |
|
784 |
action_object_object_id=revision.id, |
|
785 |
target_content_type__app_label='iconolab', |
|
786 |
target_content_type__model='annotation', |
|
787 |
target_object_id=annotation.id |
|
788 |
).unread() |
|
789 |
if ann_author_notified: |
|
790 |
ann_author_notified.first().mark_as_read() |
|
791 |
context['notified_revision'] = True |
|
792 |
if request.user.is_authenticated() and revision.author == request.user: |
|
793 |
rev_author_notified = Notification.objects.filter( |
|
794 |
recipient=request.user, |
|
795 |
action_object_content_type__app_label='iconolab', |
|
796 |
action_object_content_type__model='annotationrevision', |
|
797 |
action_object_object_id=revision.id, |
|
798 |
target_content_type__app_label='iconolab', |
|
799 |
target_content_type__model='annotation', |
|
800 |
target_object_id=annotation.id |
|
801 |
).unread() |
|
802 |
if rev_author_notified: |
|
803 |
rev_author_notified.first().mark_as_read() |
|
804 |
context['notified_revision'] = True |
|
805 |
return render(request, 'iconolab/detail_revision.html', context) |
|
806 |
||
807 |
||
808 |
class MergeProposalView(View, ContextMixin, IconolabObjectView): |
|
809 |
""" |
|
810 |
View that displays the merge form, used when a user wants to "study" a revision because it was submitted from an older revision than the current revision (thus |
|
811 |
the two revisions don't have the same parents and there is a conflict) |
|
812 |
""" |
|
813 |
def get_context_data(self, **kwargs): |
|
814 |
context = super(MergeProposalView, self).get_context_data(**kwargs) |
|
815 |
context['collection_name'] = self.kwargs.get('collection_name', '') |
|
816 |
context['image_guid'] = self.kwargs.get('image_guid', '') |
|
817 |
context['annotation_guid'] = self.kwargs.get('annotation_guid', '') |
|
818 |
context['revision_guid'] = self.kwargs.get('revision_guid', '') |
|
819 |
return context |
|
820 |
||
821 |
def get(self, request, *args, **kwargs): |
|
822 |
success, result = self.check_kwargs(kwargs) |
|
823 |
if success: |
|
824 |
(collection, image, annotation, revision,) = result |
|
825 |
else: |
|
826 |
return result(request) |
|
827 |
# Only show merge form if there is a revision to merge AND the current user is the annotation author |
|
828 |
if revision.state != AnnotationRevision.AWAITING or request.user != annotation.author: |
|
829 |
return RedirectView.as_view( |
|
830 |
url=reverse('revision_detail', |
|
831 |
kwargs={ |
|
832 |
'collection_name': collection.name, |
|
833 |
'image_guid': image.image_guid, |
|
834 |
'annotation_guid': annotation.annotation_guid, |
|
835 |
'revision_guid': revision.revision_guid |
|
836 |
} |
|
837 |
) |
|
838 |
)(request) |
|
839 |
# Auto-accepts the revision only if the proper query arg is set and only if the revision parent is the current revision |
|
840 |
if 'auto_accept' in request.GET and request.GET['auto_accept'] in ['True', 'true', '1', 'yes'] and revision.parent_revision == annotation.current_revision: |
|
841 |
annotation.validate_existing_revision(revision) |
|
842 |
return RedirectView.as_view( |
|
843 |
url=reverse('annotation_detail', |
|
844 |
kwargs={ |
|
845 |
'collection_name': collection.name, |
|
846 |
'image_guid': image.image_guid, |
|
847 |
'annotation_guid': annotation.annotation_guid |
|
848 |
} |
|
849 |
) |
|
850 |
)(request) |
|
851 |
# Auto-reject the revision only if the proper query arg is set |
|
852 |
if 'auto_reject' in request.GET and request.GET['auto_reject'] in ['True', 'true', '1', 'yes']: |
|
853 |
annotation.reject_existing_revision(revision) |
|
854 |
return RedirectView.as_view( |
|
855 |
url=reverse('annotation_detail', |
|
856 |
kwargs={ |
|
857 |
'collection_name': collection.name, |
|
858 |
'image_guid': image.image_guid, |
|
859 |
'annotation_guid': annotation.annotation_guid |
|
860 |
} |
|
861 |
) |
|
862 |
)(request) |
|
863 |
||
864 |
context = self.get_context_data(**kwargs) |
|
865 |
context['collection'] = collection |
|
866 |
context['image'] = image |
|
867 |
context['annotation'] = annotation |
|
868 |
# Proposal data |
|
869 |
context['proposal_revision'] = revision |
|
870 |
context['proposal_tags_data'] = revision.get_tags_json() |
|
871 |
context['proposal_comment'] = revision.creation_comment.first() |
|
872 |
# Parent data |
|
873 |
context['parent_revision'] = revision.parent_revision |
|
874 |
context['parent_tags_data'] = revision.parent_revision.get_tags_json() |
|
875 |
context['parent_comment'] = revision.parent_revision.creation_comment.first() |
|
876 |
# Current data |
|
877 |
context['current_revision'] = annotation.current_revision |
|
878 |
context['current_tags_data'] = annotation.current_revision.get_tags_json() |
|
879 |
context['current_comment'] = annotation.current_revision.creation_comment.first() |
|
880 |
||
881 |
merge_form = AnnotationRevisionForm(instance=revision) |
|
882 |
context['merge_form'] = merge_form |
|
883 |
return render(request, 'iconolab/merge_revision.html', context) |
|
884 |
||
885 |
def post(self, request, *args, **kwargs): |
|
886 |
# Handle merge form submit here |
|
887 |
success, result = self.check_kwargs(kwargs) |
|
888 |
if success: |
|
889 |
(collection, image, annotation, revision) = result |
|
890 |
else: |
|
891 |
return result(request) |
|
892 |
collection_name = kwargs['collection_name'] |
|
893 |
image_guid = kwargs['image_guid'] |
|
894 |
annotation_guid = kwargs['annotation_guid'] |
|
895 |
revision_guid = kwargs['revision_guid'] |
|
896 |
||
897 |
merge_revision_form = AnnotationRevisionForm(request.POST) |
|
898 |
if merge_revision_form.is_valid(): |
|
899 |
revision_title = merge_revision_form.cleaned_data['title'] |
|
900 |
revision_description = merge_revision_form.cleaned_data['description'] |
|
901 |
revision_fragment = merge_revision_form.cleaned_data['fragment'] |
|
902 |
revision_tags_json = merge_revision_form.cleaned_data['tags'] |
|
903 |
new_revision = annotation.merge_existing_revision(revision_title, revision_description, revision_fragment, revision_tags_json, revision) |
|
904 |
revision_comment = merge_revision_form.cleaned_data['comment'] |
|
905 |
comment = IconolabComment.objects.create( |
|
906 |
comment = revision_comment, |
|
907 |
revision = new_revision, |
|
908 |
content_type = ContentType.objects.get(app_label='iconolab', model='annotation'), |
|
909 |
content_object = annotation, |
|
910 |
site = Site.objects.get(id=settings.SITE_ID), |
|
911 |
object_pk = annotation.id, |
|
912 |
user = request.user, |
|
913 |
user_name = request.user.username |
|
914 |
) |
|
915 |
return RedirectView.as_view(url=reverse('annotation_detail', kwargs={'collection_name': collection_name, 'image_guid': image_guid, 'annotation_guid': annotation_guid}))(request) |
|
916 |
context = self.get_context_data(**kwargs) |
|
917 |
context['image'] = image |
|
918 |
context['merge_form'] = merge_revision_form |
|
919 |
context['annotation'] = annotation |
|
920 |
# Proposal data |
|
921 |
context['proposal_revision'] = revision |
|
922 |
context['proposal_tags_data'] = revision.get_tags_json() |
|
923 |
context['proposal_comment'] = revision.creation_comment.first() |
|
924 |
# Parent data |
|
925 |
context['parent_revision'] = revision.parent_revision |
|
926 |
context['parent_tags_data'] = revision.parent_revision.get_tags_json() |
|
927 |
context['parent_comment'] = revision.parent_revision.creation_comment.first() |
|
928 |
# Current data |
|
929 |
context['current_revision'] = annotation.current_revision |
|
930 |
context['current_tags_data'] = annotation.current_revision.get_tags_json() |
|
931 |
context['current_comment'] = annotation.current_revision.creation_comment.first() |
|
932 |
return render(request, 'iconolab/merge_revision.html', context) |