--- a/src/iconolab/models.py Fri Aug 05 15:32:49 2016 +0200
+++ b/src/iconolab/models.py Fri Aug 12 10:28:11 2016 +0200
@@ -94,6 +94,18 @@
def __str__(self):
return self.name
+
+ @property
+ def collection(self):
+ return self.item.collection.name
+
+ @property
+ def title(self):
+ return self.item.metadatas.title
+
+ @property
+ def description(self):
+ return self.item.metadatas.description
class AnnotationManager(models.Manager):
@@ -191,6 +203,10 @@
def awaiting_revisions_count(self):
return self.revisions.filter(state=AnnotationRevision.AWAITING).distinct().count()
+ @property
+ def tags(self):
+ return [tag.label for tag in self.current_revision.tags.all()]
+
# Call to create a new revision, possibly from a merge
@transaction.atomic
--- a/src/iconolab/search_indexes.py Fri Aug 05 15:32:49 2016 +0200
+++ b/src/iconolab/search_indexes.py Fri Aug 12 10:28:11 2016 +0200
@@ -10,15 +10,11 @@
title = indexes.CharField(model_attr='current_revision__title')
description = indexes.CharField(model_attr='current_revision__description')
- tags = indexes.MultiValueField()
+ tags = indexes.MultiValueField(model_attr='tags')
## tags
def get_model(self):
return Annotation
- def prepare_tags(self, annotation):
- return ["toto", "titi", "sesl"]
-
-
def index_queryset(self, using=None):
- return self.get_model().objects.filter(created__lte=datetime.datetime.now()).distinct('current_revision_id');
\ No newline at end of file
+ return self.get_model().objects.filter(created__lte=datetime.datetime.now())
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/search_indexes/__init__.py Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,2 @@
+from .indexes import AnnotationIndex, ImageIndex
+__all__ = ['AnnotationIndex', 'ImageIndex']
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/search_indexes/forms.py Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,47 @@
+from django import forms
+from haystack.forms import SearchForm
+from iconolab.models import Image, Annotation
+
+
+
+
+#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")) )
+
+ def __init__(self, *args, **kwargs):
+
+ super(IconolabSearchForm, self).__init__(*args, **kwargs)
+
+ def get_realm_queryset(self, qs, realm):
+
+ if realm == 'image':
+ qs = qs.models(Image).load_all_queryset(Image, Image.objects.select_related('item', 'item__metadatas'))
+ qs = qs.filter(collection='stdie')
+ if realm == 'annotation':
+ qs = qs.models(Annotation).load_all_queryset(Annotation, Annotation.objects.select_related('image', 'stats', 'current_revision', 'author'))
+ return qs
+
+ def search(self):
+
+ selected_realm = self.cleaned_data.get("realm")
+ selected_model = get_selected_model(selected_realm)
+ #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()
+ return qs
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/search_indexes/indexes.py Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,37 @@
+import datetime
+from haystack import indexes
+from iconolab.models import Annotation, Image
+
+class ImageIndex(indexes.SearchIndex, indexes.Indexable):
+ text = indexes.CharField(document=True, use_template=True)
+
+ title = indexes.CharField(model_attr='item__metadatas__title')
+ description = indexes.CharField(model_attr='item__metadatas__description')
+ collection = indexes.CharField(model_attr='item__collection__name')
+ tags = indexes.MultiValueField()
+
+ def get_model(self):
+ return Image
+
+ def prepare_tags(self, object):
+ return ["radical", "you better", "yes"]
+
+ def index_queryset(self, using=None):
+ return self.get_model().objects.filter(created__lte=datetime.datetime.now())
+
+
+class AnnotationIndex(indexes.SearchIndex, indexes.Indexable):
+
+ ##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')
+
+ ## tags
+ def get_model(self):
+ return Annotation
+
+ def index_queryset(self, using=None):
+ return self.get_model().objects.filter(created__lte=datetime.datetime.now())
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/search_indexes/query.py Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,18 @@
+from haystack.query import RelatedSearchQuerySet
+from iconolab.models import Annotation, Image
+from pprint import pprint
+
+class IconolabRelatedQuerySet(RelatedSearchQuerySet):
+ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/search_indexes/views.py Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,41 @@
+from haystack.generic_views import SearchView
+from iconolab.search_indexes.forms import IconolabSearchForm
+from iconolab.search_indexes.query import IconolabRelatedQuerySet
+from django.shortcuts import HttpResponse
+
+from pprint import pprint
+
+#override Search and Related QuerySet here
+class IconolabSearchView(SearchView):
+ form_class = IconolabSearchForm
+ queryset = IconolabRelatedQuerySet()
+ template_name = "search/default_search.html"
+ paginate_by = 10
+ load_all = True
+
+ templates_map = {
+ "image": "search/image_search.html",
+ "annotation": "search/annotation_search.html"
+ }
+
+ def get(self, request, *args, **kwargs):
+ self.current_realm = request.GET['realm']
+ return super(IconolabSearchView, self).get(request,*args, **kwargs)
+
+ def get_queryset(self):
+ qs = super(IconolabSearchView, self).get_queryset()
+ return qs
+
+ def get_template_names(self):
+ template = IconolabSearchView.templates_map[self.current_realm]
+ if template is None:
+ template = IconolabSearchView.template_name
+
+ 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/templates/iconolab/collection_home.html Fri Aug 05 15:32:49 2016 +0200
+++ b/src/iconolab/templates/iconolab/collection_home.html Fri Aug 12 10:28:11 2016 +0200
@@ -11,7 +11,7 @@
<ul class="image-list-wrapper list-inline">
- <p><strong>Images du fond</strong></p>
+ <p><strong>Images du fonds</strong></p>
{% for item in collection.items.all %}
<li class="small-image-wrapper">
--- a/src/iconolab/templates/partials/header.html Fri Aug 05 15:32:49 2016 +0200
+++ b/src/iconolab/templates/partials/header.html Fri Aug 12 10:28:11 2016 +0200
@@ -17,13 +17,8 @@
{% if collection_name %}<li><a href="{% url 'collection_home' collection_name %}">Contribuer</a></li>{% endif %}
</ul>
- <form class="navbar-form navbar-left" role="search">
- <div class="form-group">
- <input type="text" class="form-control" placeholder="Trouver une image...">
- </div>
- <button type="submit" class="btn btn-default">Rechercher</button>
- </form>
-
+ {% include "partials/header_search_form.html"%}
+
<ul class="nav navbar-nav navbar-right">
{% if request.user.is_authenticated %}
{% notifications_unread as unread_count %}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/partials/header_search_form.html Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,15 @@
+<form method="GET" action="{% url 'haystack_search' %}" class="navbar-form navbar-left" role="search">
+
+ <div class="form-group">
+ <input name="q" type="text" class="form-control" placeholder="Trouver une image...">
+ </div>
+
+ <div class="form-group">
+ <select name="realm" class="form-control">
+ <option value="image">Images</option>
+ <option value="innotation">Annotations</option>
+ </select>
+ </div>
+
+ <button type="submit" class="btn btn-default">Rechercher</button>
+</form>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/search/annotation_search.html Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,61 @@
+{% extends 'iconolab_base.html' %}
+
+{% load thumbnail %}
+{% load iconolab_tags %}
+
+{% block content %}
+
+ <h2>Recherche</h2>
+
+ <form method="get" action=".">
+ <table>
+
+ <tr>
+ <td> {{ form.as_p }} </td>
+
+ <td>
+ <input style="margin:0px" type="submit" value="Rechercher">
+ </td>
+ </tr>
+
+ </table>
+
+ {% if query %}
+
+ <h3><strong>{{ page_obj.paginator.count }}</strong> annotation(s)</h3>
+
+ {% for result in page_obj.object_list %}
+
+ {% 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 }}" />
+ <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>
+
+ </div>
+ {% endthumbnail %}
+
+
+ <p>
+ <a href="{{ result.object.get_absolute_url }}">{{ result.object.current_revision.title }}</a>
+ </p>
+ {% empty %}
+ <p>Aucune annotation n'a été trouvée.</p>
+ {% endfor %}
+
+ {% if page_obj.has_previous or page_obj.has_next %}
+ <div>
+ {% if page_obj.has_previous %}<a href="?q={{ query }}&page={{ page_obj.previous_page_number }}">{% endif %}« Previous{% if page_obj.has_previous %}</a>{% endif %}
+ |
+ {% if page_obj.has_next %}<a href="?q={{ query }}&page={{ page_obj.next_page_number }}">{% endif %}Next »{% if page_obj.has_next %}</a>{% endif %}
+ </div>
+ {% endif %}
+ {% else %}
+ {# Show some example queries to run, maybe query syntax, something else? #}
+ {% endif %}
+ </form>
+{% endblock %}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/search/default_search.html Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,23 @@
+{% extends 'iconolab_base.html' %}
+
+{% load thumbnail %}
+{% load iconolab_tags %}
+
+{% block content %}
+
+ <h2>Recherche</h2>
+
+ <form method="get" action=".">
+ <table>
+
+ <tr>
+ <td> {{ form.as_p }} </td>
+ <td>
+ <input style="margin:0px" type="submit" value="Rechercher">
+ </td>
+ </tr>
+
+ </table>
+
+ </form>
+{% endblock %}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/search/image_search.html Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,54 @@
+{% extends 'iconolab_base.html' %}
+
+{% load thumbnail %}
+{% load iconolab_tags %}
+
+{% block content %}
+
+ <h2>Recherche</h2>
+
+ <form method="get" action=".">
+ <table>
+
+ <tr>
+ <td> {{ form.as_p }} </td>
+
+ <td>
+ <input style="margin:0px" type="submit" value="Rechercher">
+ </td>
+ </tr>
+
+ </table>
+
+ {% if query %}
+
+ <h3><strong>{{ page_obj.paginator.count }}</strong> image(s)</h3>
+
+ {% for result in page_obj.object_list %}
+
+ {% 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 }}" />
+ </div>
+ {% endthumbnail %}
+
+ <p>
+ <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a>
+ <span>collection {{result.object.collection}}</span>
+ </p>
+ {% empty %}
+ <p>No results found.</p>
+ {% endfor %}
+
+ {% if page_obj.has_previous or page_obj.has_next %}
+ <div>
+ {% if page_obj.has_previous %}<a href="?q={{ query }}&page={{ page_obj.previous_page_number }}">{% endif %}« Previous{% if page_obj.has_previous %}</a>{% endif %}
+ |
+ {% if page_obj.has_next %}<a href="?q={{ query }}&page={{ page_obj.next_page_number }}">{% endif %}Next »{% if page_obj.has_next %}</a>{% endif %}
+ </div>
+ {% endif %}
+ {% else %}
+ {# Show some example queries to run, maybe query syntax, something else? #}
+ {% endif %}
+ </form>
+{% endblock %}
\ No newline at end of file
--- a/src/iconolab/templates/search/indexes/iconolab/annotation_text.txt Fri Aug 05 15:32:49 2016 +0200
+++ b/src/iconolab/templates/search/indexes/iconolab/annotation_text.txt Fri Aug 12 10:28:11 2016 +0200
@@ -2,3 +2,4 @@
{{ object.current_revision.description }}
+{{ object.tags }}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/search/indexes/iconolab/image_text.txt Fri Aug 12 10:28:11 2016 +0200
@@ -0,0 +1,7 @@
+{{ object.item.metadatas.title }}
+
+{{ object.item.metadatas.description }}
+
+{{ object.tags }}
+
+samedi
\ No newline at end of file
--- a/src/iconolab/urls.py Fri Aug 05 15:32:49 2016 +0200
+++ b/src/iconolab/urls.py Fri Aug 12 10:28:11 2016 +0200
@@ -16,32 +16,38 @@
from django.core.urlresolvers import reverse_lazy
from django.conf.urls import url, include
from django.contrib import admin
-from . import views
+from iconolab import views
+from iconolab.search_indexes.views import IconolabSearchView
from . import settings
from django.conf.urls.static import static
from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
+import notifications.urls
urlpatterns = [
- url(r'^$', views.RedirectView.as_view(url=reverse_lazy("home"))),
+ url(r'^$', views.iconolab.RedirectView.as_view(url=reverse_lazy("home"))),
url(r'^admin/', admin.site.urls),
- url(r'^home$', views.GlobalHomepageView.as_view(), name="home"),
- url(r'^collections/(?P<collection_name>[a-z]+)$', views.CollectionHomepageView.as_view(), name='collection_home'), # Home fond
- url(r'^collections/(?P<collection_name>[a-z]+)/items/(?P<item_guid>[^/]+)$', views.ShowItemView.as_view(), name='item_detail'),
- url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)$', views.ShowImageView.as_view(), name='image_detail'),
- url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/create$', login_required(views.CreateAnnotationView.as_view()), name='annotation_create'),
- url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/detail$', views.ShowAnnotationView.as_view(), name='annotation_detail'),
- url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/edit$', login_required(views.EditAnnotationView.as_view()), name='annotation_edit'),
- url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/detail', views.ShowRevisionView.as_view(), name='revision_detail'),
- url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/merge$', login_required(views.MergeProposalView.as_view()), name='annotation_merge'),
- url(r'errors/404', views.NotFoundErrorView.as_view(), name="404error"),
+ url(r'^home$', views.iconolab.GlobalHomepageView.as_view(), name="home"),
+ url(r'^collections/(?P<collection_name>[a-z]+)$', views.iconolab.CollectionHomepageView.as_view(), name='collection_home'), # Home fond
+ url(r'^collections/(?P<collection_name>[a-z]+)/items/(?P<item_guid>[^/]+)$', views.iconolab.ShowItemView.as_view(), name='item_detail'),
+ url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)$', views.iconolab.ShowImageView.as_view(), name='image_detail'),
+ url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/create$', login_required(views.iconolab.CreateAnnotationView.as_view()), name='annotation_create'),
+ url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/detail$', views.iconolab.ShowAnnotationView.as_view(), name='annotation_detail'),
+ url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/edit$', login_required(views.iconolab.EditAnnotationView.as_view()), name='annotation_edit'),
+ url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/detail', views.iconolab.ShowRevisionView.as_view(), name='revision_detail'),
+ url(r'^collections/(?P<collection_name>[a-z]+)/images/(?P<image_guid>[^/]+)/annotations/(?P<annotation_guid>[^/]+)/revisions/(?P<revision_guid>[^/]+)/merge$', login_required(views.iconolab.MergeProposalView.as_view()), name='annotation_merge'),
+ url(r'^user/(?P<slug>[a-z0-9\-]+)/home/?$', views.iconolab.UserHomeView.as_view(), name="user_home"),
+ url(r'^user/notifications/all/?$', login_required(views.iconolab.UserNotificationsView.as_view()), name="user_notifications"),
+ url(r'^errors/404', views.iconolab.NotFoundErrorView.as_view(), name="404error"),
url(r'^rest', include('restapi.urls')),
url(r'^account/', include('iconolab.auth.urls', namespace='account')),
url(r'^comments/', include('django_comments_xtd.urls')),
- url(r'^comments/annotation/post', views.post_comment_iconolab, name="post_comment"),
- url(r'^search/', include('haystack.urls')),
+ url(r'^comments/annotation/post', views.comments.post_comment_iconolab, name="post_comment"),
+ url('^user/notifications/', include(notifications.urls, namespace='notifications')),
+ url(r'^search/$', IconolabSearchView.as_view(), name="haystack_search"),
+ #url(r'^search/', include('haystack.urls'), name="search_iconolab"),
]
urlpatterns += staticfiles_urlpatterns()
-urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)