Merge with e13fed7f0837208731b2f9b1472fe2284966120d
authordurandn
Thu, 18 Aug 2016 10:58:55 +0200
changeset 137 454e39dced1f
parent 136 81d82b1f431a (current diff)
parent 125 e13fed7f0837 (diff)
child 138 2c2d394904db
child 143 c68983a2efac
Merge with e13fed7f0837208731b2f9b1472fe2284966120d
src/iconolab/models.py
src/iconolab/settings/dev.py.tmpl
src/iconolab/urls.py
--- a/.hgignore	Thu Aug 18 10:57:00 2016 +0200
+++ b/.hgignore	Thu Aug 18 10:58:55 2016 +0200
@@ -7,7 +7,7 @@
 ^src/iconolab/static/iconolab/js/node_modules/
 ^src/iconolab/static/iconolab/js/iconolab-bundle/node_modules/
 ^src/iconolab/static/iconolab/js/iconolab-bundle/dist/
-
+\.orig$
 
 ^web/*
 ^\.pydevproject$
--- a/src/iconolab/models.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/models.py	Thu Aug 18 10:58:55 2016 +0200
@@ -266,6 +266,10 @@
         return self.revisions.filter(state=AnnotationRevision.AWAITING).distinct().count()
     
     @property
+    def collection(self):
+        return self.image.collection
+
+    @property
     def tags(self):
         return [tag.label for tag in self.current_revision.tags.all()]
     
--- a/src/iconolab/search_indexes/__init__.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/search_indexes/__init__.py	Thu Aug 18 10:58:55 2016 +0200
@@ -1,2 +1,2 @@
 from .indexes import AnnotationIndex, ImageIndex 
-__all__ = ['AnnotationIndex', 'ImageIndex']
\ No newline at end of file
+__all__ = ['AnnotationIndex', 'ImageIndex', 'RevisionSignalProcessor']
\ No newline at end of file
--- a/src/iconolab/search_indexes/forms.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/search_indexes/forms.py	Thu Aug 18 10:58:55 2016 +0200
@@ -5,42 +5,45 @@
 
 
 
-#def get_available_choices():
-
-def get_selected_model(type):
-	
-	available_models = {
-		'image': Image,
-		'annotation': Annotation
-	}
-
-	return available_models[type]
-
-
 class IconolabSearchForm(SearchForm):
 
-	realm = forms.ChoiceField(required=False, choices=(("image","Image"), ("annotation","Annotation")) )
+	model_type = forms.ChoiceField(required=False, choices=(("images","Image"), ("annotations","Annotation")) )
 	
 	def __init__(self, *args, **kwargs):
-		
+		self.collection_name = kwargs.pop("collection_name")
+		selected_model_type =  kwargs.pop("model_type", None)
+
+		if selected_model_type is not None: 
+			data = kwargs.get("data", None)
+			if data:
+				data = data.copy()
+				data["model_type"] = selected_model_type
+				kwargs['data'] = data
+
 		super(IconolabSearchForm, self).__init__(*args, **kwargs)
+	
+	def no_query_found(self):
+		print("inside no_query_found")
+		return self.searchqueryset.all()
 
-	def get_realm_queryset(self, qs, realm):
+	def get_model_type_queryset(self, qs, model_type):
 		
-		if realm == 'image':
+		if model_type == 'images':
 			qs = qs.models(Image).load_all_queryset(Image, Image.objects.select_related('item', 'item__metadatas'))
-		if realm == 'annotation':
+		if model_type == 'annotations':
 			qs = qs.models(Annotation).load_all_queryset(Annotation, Annotation.objects.select_related('image', 'stats', 'current_revision', 'author'))
+		
+		if self.collection_name is not None:
+			qs = qs.filter(collection = self.collection_name)
+
 		return qs
 
 	def search(self):
-		
-		selected_realm = self.cleaned_data.get("realm")
-		selected_model = get_selected_model(selected_realm)
+		selected_type = self.cleaned_data.get("model_type")
 		#load all if q empty
 		qs = super(IconolabSearchForm, self).search()
 		if qs.count() == 0:
 			return qs
 		else:
-			qs = self.get_realm_queryset(qs, selected_realm).load_all()
+			qs = self.get_model_type_queryset(qs, selected_type).load_all()
 		return qs
\ No newline at end of file
--- a/src/iconolab/search_indexes/indexes.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/search_indexes/indexes.py	Thu Aug 18 10:58:55 2016 +0200
@@ -5,7 +5,7 @@
 class ImageIndex(indexes.SearchIndex, indexes.Indexable):
     text = indexes.CharField(document=True, use_template=True)
 
-    collection = indexes.CharField(model_attr='collection')
+    collection = indexes.CharField(model_attr="collection")
     authors = indexes.CharField(model_attr="authors")
     school = indexes.CharField(model_attr="school")
     designation = indexes.CharField(model_attr="designation")
@@ -31,10 +31,11 @@
     ##indexed field
     text = indexes.CharField(document=True, use_template=True)
 
-    title = indexes.CharField(model_attr='current_revision__title')
-    description = indexes.CharField(model_attr='current_revision__description')
-    tags = indexes.MultiValueField(model_attr='tags')
-
+    title = indexes.CharField(model_attr="current_revision__title")
+    description = indexes.CharField(model_attr="current_revision__description")
+    collection = indexes.CharField(model_attr="collection") 
+    tags = indexes.MultiValueField(model_attr="tags")
+    
     ## tags
     def get_model(self):
         return Annotation
--- a/src/iconolab/search_indexes/query.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/search_indexes/query.py	Thu Aug 18 10:58:55 2016 +0200
@@ -6,13 +6,15 @@
 	def __init__(self, using=None, query=None):
 		super(IconolabRelatedQuerySet, self).__init__(using=using, query=query)
 
-	#def in_bulk(self, ids):
-	#	results = {}
-	#	int_ids = [ int(id) for id in ids]
-	#	# Ne garder que les images
-	#	annotations = Image.objects.filter(pk__in = int_ids)
-	#	
-	#	for annotation in annotations:
-	#		results[annotation.pk] = annotation
-	#		
-	#	return results
+	def in_bulk(self, ids):
+		results = {}
+		int_ids = [ int(id) for id in ids]
+		print("in_bulk")
+		print(int_ids)
+		# Ne garder que les images
+		annotations = Annotation.objects.filter(pk__in = int_ids)
+		
+		for annotation in annotations:
+			results[annotation.pk] = annotation
+			
+		return results
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/search_indexes/signals.py	Thu Aug 18 10:58:55 2016 +0200
@@ -0,0 +1,26 @@
+from iconolab.models import Image, AnnotationRevision, Annotation
+from haystack import signals
+from django.db import models
+from iconolab.signals.handlers import revision_created, revision_accepted
+import logging
+
+logger = logging.getLogger(__name__)
+
+# update / create new index when a new revision is accepted
+# Then update images tags related to this revision
+class RevisionSignalProcessor(signals.BaseSignalProcessor):
+	
+	def setup(self):
+		revision_created.connect(self.handle_revision, sender=AnnotationRevision)
+		revision_accepted.connect(self.handle_revision, sender=AnnotationRevision)
+
+	def handle_revision(self, **kwargs):
+		revision_instance = kwargs.get("instance", None)
+		if revision_instance and revision_instance.state in [AnnotationRevision.ACCEPTED]:
+			annotation = revision_instance.annotation
+			image_annotation = revision_instance.annotation.image
+			self.handle_save(Annotation, annotation) 
+			self.handle_save(Image, image_annotation)##useful for tag		
+
+	def teardown(self):
+		revision_accepted.disconnect(self.handle_accepted_revision, sender=AnnotationRevision)
\ No newline at end of file
--- a/src/iconolab/search_indexes/views.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/search_indexes/views.py	Thu Aug 18 10:58:55 2016 +0200
@@ -1,41 +1,98 @@
 from haystack.generic_views import SearchView
+from haystack.query import RelatedSearchQuerySet
 from iconolab.search_indexes.forms import IconolabSearchForm
 from iconolab.search_indexes.query import IconolabRelatedQuerySet
-from django.shortcuts import HttpResponse
+from django.shortcuts import HttpResponse, redirect
+from django.core.urlresolvers import reverse
+from django.views.generic import RedirectView
+from iconolab.models import Collection
 
 from pprint import pprint
 
 #override Search and Related QuerySet here
 class IconolabSearchView(SearchView):
 	form_class = IconolabSearchForm
-	queryset = IconolabRelatedQuerySet()
+	queryset = RelatedSearchQuerySet()
 	template_name = "search/default_search.html"
 	paginate_by = 10
 	load_all = True
 
 	templates_map = {
-		"image": "search/image_search.html",
-		"annotation": "search/annotation_search.html"
+		"images": "search/image_search.html",
+		"annotations": "search/annotation_search.html"
 	}
 
+	def complete_url(self, url):
+		query = self.request.GET.get("q", None)
+		page = self.request.GET.get("page", None)
+
+		queryargs = [] 
+		query_string = ""
+
+		if query is not None:
+			queryargs.append("q=" + query)
+		
+		if page is not None:
+			queryargs.append("page="+page)
+
+		if len(queryargs):
+			query_string = "&".join(queryargs)
+			url += "?" + query_string
+
+		return url
+
 	def get(self, request, *args, **kwargs):
-		self.current_realm = request.GET['realm']
-		return super(IconolabSearchView, self).get(request,*args, **kwargs)
+
+		self.model_type = request.GET.get('model_type', None)
+		collection_name = self.kwargs.get('collection_name', None)
+
+		if self.model_type is not None:
+			if collection_name is None:
+				#redirect to all_model_type
+				redirect_url = reverse('model_search', kwargs={'model_type': self.model_type}) 
+				return redirect(self.complete_url(redirect_url))
+			else:
+				redirect_url = reverse('collection_with_model_search', kwargs={'collection_name': collection_name, 'model_type':self.model_type})
+				return redirect(self.complete_url(redirect_url))
+		else:
+			has_error, redirectView = self.check_kwargs(**kwargs)
+			if has_error:
+				return redirectView(request)
+			return super(IconolabSearchView, self).get(request, *args, **kwargs)
+
+	def check_kwargs(self, **kwargs):
+		result = (False, None)
+		try:
+			collection_name = kwargs.get('collection_name', None)
+			if collection_name is None:
+				return result
+			collection = Collection.objects.get(name=kwargs.get('collection_name'))	
+		except Collection.DoesNotExist:
+			result = (True, RedirectView.as_view(url=reverse('404error'))) 
+		finally:
+			return result
 
 	def get_queryset(self):
 		qs = super(IconolabSearchView, self).get_queryset()
+		return IconolabSearchView.queryset
 		return qs
 
+	def get_form_kwargs(self):
+		kwargs = super(IconolabSearchView, self).get_form_kwargs()
+		kwargs['collection_name'] = self.kwargs.get('collection_name', None)
+		kwargs['model_type'] = self.kwargs.get('model_type', None)
+		return kwargs
+
 	def get_template_names(self):
-		template = IconolabSearchView.templates_map[self.current_realm]
-		if template is None:
+		try :
+			model_type = self.kwargs.get('model_type', None) 
+			template = IconolabSearchView.templates_map[model_type]
+		except KeyError:
 			template = IconolabSearchView.template_name
-				
-		return [template]
+		finally:
+			return [template]
 
 	def get_context_data(self, *args, **kwargs):
-		print("inside get_context_data", kwargs.get("q"))
-		print(kwargs.items())
 		context = super(IconolabSearchView, self).get_context_data(*args, **kwargs)
 		context['collection_name'] = self.kwargs.get('collection_name', '')
 		return context
\ No newline at end of file
--- a/src/iconolab/settings/dev.py.tmpl	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/settings/dev.py.tmpl	Thu Aug 18 10:58:55 2016 +0200
@@ -178,6 +178,9 @@
     },
 }
 
+# HAYSTACK_SIGNAL_PROCESSOR
+HAYSTACK_SIGNAL_PROCESSOR = 'iconolab.search_indexes.signals.RevisionSignalProcessor'
+
 CACHES = {
     'default': {
         'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
--- a/src/iconolab/templates/partials/header_search_form.html	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/templates/partials/header_search_form.html	Thu Aug 18 10:58:55 2016 +0200
@@ -1,15 +1,20 @@
-<form method="GET" action="{% url 'haystack_search' %}" class="navbar-form navbar-left" role="search">
+
+{% if collection_name %}
+	<form method="GET" action="{% url 'collection_haystack_search' collection_name %}" class="navbar-form navbar-left" role="search">
+		{% else %}
+	<form method="GET" action="{% url 'haystack_search' %}" class="navbar-form navbar-left" role="search">	
+{% endif %}
 	
 	<div class="form-group">
-	  <input name="q" type="text" class="form-control input-sm" placeholder="Trouver une image...">
+	  <input name="q" type="text" class="form-control" placeholder="Trouver une image...">
 	</div>
 	
 	<div class="form-group">
-		<select name="realm" class="form-control input-sm">
-			<option value="image">Images</option>
-			<option value="annotation">Annotations</option>
+		<select name="model_type" class="form-control">
+			<option value="images">Images</option>
+			<option value="annotations">Annotations</option>
 		</select>
 	</div>
 
-	<button type="submit" class="btn btn-default btn-sm"><i class="fa fa-search" aria-hidden="true"></i></button>
+	<button type="submit" class="btn btn-default">Rechercher</button>
 </form>
--- a/src/iconolab/templates/search/annotation_search.html	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/templates/search/annotation_search.html	Thu Aug 18 10:58:55 2016 +0200
@@ -28,21 +28,26 @@
 
             {% thumbnail result.object.image.media "400x400" crop=False as im %}
             <div class="annotation-item result" style="position:relative;">
-
-                <img v-el:small-image src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
+            
+            <a href="{% url 'annotation_detail' result.object.collection result.object.image.image_guid result.object.annotation_guid %}">
+                <img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
                 <svg width="{{ im.width }}" height="{{ im.height }}" version="1.1" style="position:absolute; top:0px; left: 0px">
                   <g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
                     <path d="{{ result.object.current_revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
                   </g>
                 </svg>
-
+            </a>
             </div>
             {% endthumbnail %}
 
+            <p>
+                <a href="{{ result.object.get_absolute_url }}">{{ result.object.current_revision.title }}</a>
+            </p>
 
-                <p>
-                    <a href="{{ result.object.get_absolute_url }}">{{ result.object.current_revision.title }}</a>
-                </p>
+            <div class="fragment-infos">
+                <a class="btn btn-default btn-xs collection-home-btn" href="{% url 'annotation_detail' result.object.collection result.object.image.image_guid result.object.annotation_guid %}"><i class="fa fa-eye"></i> Voir l'annotation</a>
+            </div>
+            
             {% empty %}
                 <p>Aucune annotation n'a été trouvée.</p>
             {% endfor %}
--- a/src/iconolab/templates/search/image_search.html	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/templates/search/image_search.html	Thu Aug 18 10:58:55 2016 +0200
@@ -28,14 +28,17 @@
 
             {% thumbnail result.object.media "400x400" crop=False as im %}
             <div class="annotation-item result" style="position:relative;">
-                <img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
+                <a href="{% url 'item_detail' result.object.collection result.object.item.item_guid %}">
+                    <img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
+                </a>
             </div>
             {% endthumbnail %}
 
                 <p>
-                    <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a>
+                    <a href="{% url 'item_detail' result.object.collection result.object.item.item_guid %}">{{ result.object.title }}</a>
                     <span>collection {{result.object.collection}}</span>
                 </p>
+                {{result.object.item}}
             {% empty %}
                 <p>No results found.</p>
             {% endfor %}
--- a/src/iconolab/templates/search/indexes/iconolab/annotation_text.txt	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/templates/search/indexes/iconolab/annotation_text.txt	Thu Aug 18 10:58:55 2016 +0200
@@ -3,3 +3,5 @@
 {{ object.current_revision.description }}
 
 {{ object.tags }}
+
+samedi
\ No newline at end of file
--- a/src/iconolab/templates/search/indexes/iconolab/image_text.txt	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/templates/search/indexes/iconolab/image_text.txt	Thu Aug 18 10:58:55 2016 +0200
@@ -9,4 +9,4 @@
 {{ object.item.metadatas.discovery_context }}
 {{ object.item.metadatas.conservation_location }}
 
-{{ object.tags }}
+{{ object.tags }}
\ No newline at end of file
--- a/src/iconolab/urls.py	Thu Aug 18 10:57:00 2016 +0200
+++ b/src/iconolab/urls.py	Thu Aug 18 10:58:55 2016 +0200
@@ -50,6 +50,12 @@
     url(r'^comments/', include('django_comments_xtd.urls')),
     url(r'^comments/annotation/post', views.comments.post_comment_iconolab, name="post_comment"),
     url('^user/notifications/', include(notifications.urls, namespace='notifications')),
+    
+    url(r'collections/(?P<collection_name>[a-z0-9\-]+)/search/(?P<model_type>[a-z0-9\-]+)', IconolabSearchView.as_view(), name="collection_with_model_search"),
+
+    url(r'^search/(?P<model_type>[a-z0-9\-]+)', IconolabSearchView.as_view(), name="model_search"),
+
+    url(r'collections/(?P<collection_name>[a-z0-9\-]+)/search', IconolabSearchView.as_view(), name="collection_haystack_search"),
     url(r'^search/$', IconolabSearchView.as_view(), name="haystack_search"),
     #url(r'^search/', include('haystack.urls'), name="search_iconolab"),
 ]