Merge with the latest changes from jverrier
authorhamidouk
Thu, 12 Jan 2012 10:19:47 +0100
changeset 357 7e234ffc2a23
parent 356 5a89838f79d4 (current diff)
parent 352 6fa2e1f8ddaa (diff)
child 358 27be3fb68776
Merge with the latest changes from jverrier
--- a/crea/inte-crea/groupe.html	Thu Jan 12 10:18:12 2012 +0100
+++ b/crea/inte-crea/groupe.html	Thu Jan 12 10:19:47 2012 +0100
@@ -113,6 +113,30 @@
                 <p><a href="#"><b>Lorem Ipsum</b></a></p>
                 <p class="font_11">par <a class="under" href="#">Ars Industrialis</a> | 1h30</p>
             </li>
+            <li class="li_media">
+                <a href="#"><img class="img_media" src="img/placeholder_16_9.jpg" width="134" height="75" /></a>
+                <div class="bulle_annot">120</div>
+                <p><a href="#"><b>Lorem Ipsum</b></a></p>
+                <p class="font_11">par <a class="under" href="#">Ars Industrialis</a> | 1h30</p>
+            </li>
+            <li class="li_media">
+                <a href="#"><img class="img_media" src="img/placeholder_16_9.jpg" width="134" height="75" /></a>
+                <div class="bulle_annot">120</div>
+                <p><a href="#"><b>Lorem Ipsum</b></a></p>
+                <p class="font_11">par <a class="under" href="#">Ars Industrialis</a> | 1h30</p>
+            </li>
+            <li class="li_media">
+                <a href="#"><img class="img_media" src="img/placeholder_16_9.jpg" width="134" height="75" /></a>
+                <div class="bulle_annot">120</div>
+                <p><a href="#"><b>Lorem Ipsum</b></a></p>
+                <p class="font_11">par <a class="under" href="#">Ars Industrialis</a> | 1h30</p>
+            </li>
+            <li class="li_media">
+                <a href="#"><img class="img_media" src="img/placeholder_16_9.jpg" width="134" height="75" /></a>
+                <div class="bulle_annot">120</div>
+                <p><a href="#"><b>Lorem Ipsum</b></a></p>
+                <p class="font_11">par <a class="under" href="#">Ars Industrialis</a> | 1h30</p>
+            </li>
             <li>
                 <p>
                     <a class="pink" href="#">1</a>
--- a/crea/inte-crea/player.html	Thu Jan 12 10:18:12 2012 +0100
+++ b/crea/inte-crea/player.html	Thu Jan 12 10:19:47 2012 +0100
@@ -44,7 +44,7 @@
                     <ul class="floatlist">
                         <li class="share_li">
                             <a href="https://twitter.com/share" class="twitter-share-button" data-count="none">Twitter</a>
-                            <script src="//platform.twitter.com/widgets.js" type="text/javascript"></script>
+                            <script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script>
                         </li>
                         <li class="share_li" style="padding-top: 3px">
                             <a name="fb_share">Partager</a> 
--- a/src/ldt/ldt/indexation/__init__.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/indexation/__init__.py	Thu Jan 12 10:19:47 2012 +0100
@@ -23,12 +23,16 @@
         title = doc.getField('title').stringValue()
         desc = doc.getField('abstract').stringValue()
         tags = doc.getField('tags').stringValue()
+        begin = doc.getField('begin').stringValue()
+        duration = doc.getField('duration').stringValue()
 
         ids['context'] = desc
         ids['title'] = title
         ids['tags'] = tags
         ids['score'] = score
         ids['lucene_id'] = i.doc
+        ids['begin'] = begin
+        ids['duration'] = duration
         contexts.append(ids)     
     
     searcher.close()
--- a/src/ldt/ldt/ldt_utils/contentindexer.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/contentindexer.py	Thu Jan 12 10:19:47 2012 +0100
@@ -101,7 +101,9 @@
                 doc.add(lucene.Field("tags", tags, lucene.Field.Store.YES, lucene.Field.Index.ANALYZED))
                 doc.add(lucene.Field("title", title, lucene.Field.Store.YES, lucene.Field.Index.ANALYZED))
                 doc.add(lucene.Field("abstract", abstract, lucene.Field.Store.YES, lucene.Field.Index.ANALYZED))
-                doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.YES, lucene.Field.Index.ANALYZED))
+                doc.add(lucene.Field("all", " ".join([tags, title, abstract]), lucene.Field.Store.YES, lucene.Field.Index.ANALYZED))        
+                doc.add(lucene.Field("begin", str(start_ts), lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
+                doc.add(lucene.Field("duration", str(duration), lucene.Field.Store.YES, lucene.Field.Index.NOT_ANALYZED))
 
                 seg = Segment(content=content,
                               iri_id=content.iri_id,
--- a/src/ldt/ldt/ldt_utils/models.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/models.py	Thu Jan 12 10:19:47 2012 +0100
@@ -158,20 +158,6 @@
             self.save()
         return self.duration    
     
-    def duration_str(self):
-        if self.duration is None:
-            return "?"
-        # We take off the milliseconds
-        sec = self.duration//1000
-        if sec < 60 :
-            return str(dur) + "s"
-        hours = sec//3600
-        min = (sec - (hours * 3600))//60
-        if min<10:
-            min_str = "0" + str(min)
-        else:
-            min_str = str(min)
-        return str(hours) + "h" + min_str
     
     def mimetype(): #@NoSelf
         def fget(self):
@@ -460,7 +446,7 @@
         self.save()
         
     def unpublish(self):
-        if not self.pk():
+        if not self.pk:
             self.save()
         self.state = 1
         everyone = Group.objects.get(name=settings.PUBLIC_GROUP_NAME)
--- a/src/ldt/ldt/ldt_utils/stat.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/stat.py	Thu Jan 12 10:19:47 2012 +0100
@@ -5,6 +5,7 @@
 
 
 def update_stat_project(project, contents=None, doc=None, update_contents=[]):
+    
     if not contents:
         contents = project.contents.all()
      
@@ -16,29 +17,34 @@
         
     for content_node in doc.xpath('/iri/annotations/content'):
         content_name = content_node.get('id')
-        content = contents.get(iri_id=content_name)
-        contribution_to_content = contributions.get(content=content)
-        
-        size_division = content.duration / number_division
-        limits = [x * size_division for x in range(number_division+1)]
-        buckets = [0] * number_division
-        nb_annotation = 0
+        content = contents.filter(iri_id=content_name)
         
-        for ann in content_node.xpath('ensemble/decoupage/elements/element'):
- 
-            begin = int(ann.get('begin'))
-            end = int(ann.get('dur')) + begin
-                    
-            buckets = find_buckets(buckets, limits, begin, end)
-            nb_annotation += 1        
-       
-        buckets = get_string_from_buckets(buckets)
-         
-        if contribution_to_content.stat != buckets or contribution_to_content.nb_annotation != nb_annotation:
-            contribution_to_content.stat = buckets
-            contribution_to_content.nb_annotation = nb_annotation
-            contribution_to_content.save()
-            update_stat_content(content)
+        # if the content referenced in the xml belongs to the
+        # fields contents of the project
+        if len(content) != 0:
+            content = content[0]
+            contribution_to_content = contributions.get(content=content)
+            
+            size_division = content.duration / number_division
+            limits = [x * size_division for x in range(number_division+1)]
+            buckets = [0] * number_division
+            nb_annotation = 0
+            
+            for ann in content_node.xpath('ensemble/decoupage/elements/element'):
+     
+                begin = int(ann.get('begin'))
+                end = int(ann.get('dur')) + begin
+                        
+                buckets = find_buckets(buckets, limits, begin, end)
+                nb_annotation += 1        
+           
+            buckets = get_string_from_buckets(buckets)
+             
+            if contribution_to_content.stat != buckets or contribution_to_content.nb_annotation != nb_annotation:
+                contribution_to_content.stat = buckets
+                contribution_to_content.nb_annotation = nb_annotation
+                contribution_to_content.save()
+                update_stat_content(content)
     
     for content in update_contents:
         update_stat_content(content)
--- a/src/ldt/ldt/ldt_utils/templates/front/front_base.html	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_base.html	Thu Jan 12 10:19:47 2012 +0100
@@ -25,8 +25,11 @@
             <h1><a href="{% url ldt.ldt_utils.views.front.front_home %}"><b>Lignes</b> de temps</a></h1>
         </li>
         <li id="li_search">
-            <form id="form_search">
-                <input id="search_text" name="q" value="" />
+            <form id="form_search" action="{% url ldt.ldt_utils.views.front.search_index %}" method="POST">
+                {% csrf_token %}
+                <!--input id="search_text" name="q" value="" /-->
+                <input id="id_search" type="text" name="search">
+                <input type="hidden" value="all" name="field">
                 <input id="search_submit" type="submit" value="{% trans 'Search' %}" />
             </form>
         <li id="li_annotation">
--- a/src/ldt/ldt/ldt_utils/templates/front/front_group.html	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_group.html	Thu Jan 12 10:19:47 2012 +0100
@@ -1,6 +1,7 @@
 {% extends "front/front_base.html" %}
 {% load i18n %}
 {% load thumbnail %}
+{% load str_duration %}
 
 {% block title %}Lignes de temps : groupe "{{group.name}}"{% endblock %}
 
@@ -21,7 +22,7 @@
         <a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}">{% thumbnail content.image "134x75" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}">{% endthumbnail %}</a>
         <div class="bulle_annot">120</div>
         <p><a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}"><b>{% if content.title|length > 69 %}{{content.title|slice:":69"}}...{% else %}{{content.title}}{% endif %}</b></a></p>
-        <p class="font_11">{% trans 'by' %} IRI | {{content.duration_str}}</p>
+        <p class="font_11">{% trans 'by' %} IRI | {{content.duration|str_duration:"h"}}</p>
     </li>
     {% endfor %}
 </ul>
--- a/src/ldt/ldt/ldt_utils/templates/front/front_home.html	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_home.html	Thu Jan 12 10:19:47 2012 +0100
@@ -1,6 +1,8 @@
 {% extends "front/front_base.html" %}
 {% load i18n %}
 {% load thumbnail %}
+{% load str_duration %}
+
 
 {% block title %}Lignes de temps : Home{% endblock %}
 
@@ -19,9 +21,9 @@
     {% for content in last_contents %}
     <li class="li_media">
         <a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}">{% thumbnail content.image "294x165" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}">{% endthumbnail %}</a>
-        <div class="bulle_annot">250</div>
+        <div class="bulle_annot">{{ content.nb_annotation }}</div>
         <p><a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}"><b>{{content.title}}</b></a></p>
-        <p>{% trans 'by' %} IRI | {{content.duration_str}}</p>
+        <p>{% trans 'by' %} IRI | {{content.duration|str_duration:"h"}}</p>
     </li>
     {% endfor %}
 </ul>
@@ -33,9 +35,9 @@
     {% for content in most_contents %}
     <li class="li_media">
         <a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}">{% thumbnail content.image "134x75" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}">{% endthumbnail %}</a>
-        <div class="bulle_annot">120</div>
+        <div class="bulle_annot">{{ content.nb_annotation }}</div>
         <p><a href="{% url ldt.ldt_utils.views.front.annot_content content.iri_id %}"><b>{% if content.title|length > 69 %}{{content.title|slice:":69"}}...{% else %}{{content.title}}{% endif %}</b></a></p>
-        <p class="font_11">{% trans 'by' %} IRI | {{content.duration_str}}</p>
+        <p class="font_11">{% trans 'by' %} IRI | {{content.duration|str_duration:"h"}}</p>
     </li>
     {% endfor %}
 </ul>
@@ -50,7 +52,7 @@
             <a href="{% url ldt.ldt_utils.views.front.group_info group.id %}">{% thumbnail group.profile.image "54x40" format="PNG" crop="center" as im %}<img src="{{ im.url }}" class="img_media" width="{{ im.width }}" height="{{ im.height }}">{% endthumbnail %}</a>
         </div>
         <div class="txt_groupes_actifs">
-            <div class="bulle_people">57</div>
+            <div class="bulle_people">{{ group.user_set.count }}</div>
             <div class="bulle_annot">32</div>
             <p><a href="{% url ldt.ldt_utils.views.front.group_info group.id %}" class="under"><b>{{group.name}}</b></a></p>
             <p>{% if group.profile.description|length > 69 %}{{group.profile.description|safe|slice:":69"}}...{% else %}{{group.profile.description|safe}}{% endif %}</p>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/ldt_utils/templates/front/front_search_results.html	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,114 @@
+{% extends "front/front_base.html" %}
+{% load i18n %}
+{% load thumbnail %}
+{% load str_duration %}
+
+{% block title %}Lignes de temps : {% trans 'search' %} ""{% endblock %}
+
+{% block css_import %}
+{{block.super}}
+<link rel="stylesheet" href="{{LDT_MEDIA_PREFIX}}css/front_search.css" type="text/css"/>
+{% endblock %}
+
+{% block body %}
+{{block.super}}
+
+{% if msg %}
+{{ msg }}
+{% else %}
+  {% ifequal nb_results 0 %}
+    {% blocktrans %} No results for <b>{{ search }}</b>.{% endblocktrans %}
+  {% else %}
+<!-- TABLE POUR ALIGNER À LA VERTICALE -->
+    <table id="tbl_rech">
+    <tr>
+<!-- LISTE DES RÉSULTATS -->
+        <td>
+        <ul class="floatlist" id="liste_resultats">
+    <!-- titre "Résultats de recherche" et options -->
+            <li id="li_haut_resultats">
+                <ul class="floatlist" id="ul_haut_resultats">
+                    <li id="title_resultats">
+                        <h2>{% trans "Search results for " %} <b> {{ search }}</b></h2>
+                    </li>
+                    <li>
+                        <p id="p_nb_resultats">{{ nb_results }} {% trans "Result" %}{{ nb_results|pluralize }}</p>
+                    </li>
+                    <!--li id="resultats_options">options</li-->
+                </ul>
+            </li>
+    <!-- Médias trouvés -->
+    
+        <!-- Média -->
+        {% autoescape off %}
+        {% for res in results.object_list %}
+            <li class="li_result_media">
+                <div class="titre_result_media">
+                    <div class="h3_result_media">
+                        <h3>{{res.content_title|capfirst}}</h3>
+                    </div>
+                    <div class="duree_result_media">
+                        <p>{{res.content.duration}}</p>
+                    </div>
+                    <div class="graphe_result_media">
+                        <img src="img/placeholder_media_graph.png" width="340" height="25" alt="graph de volume" />
+                    </div>
+                </div>
+        
+            <!-- Segments du média -->
+                <ul class="floatlist list_segments">
+                {% for segment in res.list %}
+                    <li class="li_segment">
+                        <div class="left_segment">
+                            <div class="color_zone" style="background: #f49af5;"></div>
+                            <a href="{% url ldt.ldt_utils.views.lignesdetemps.index_segment segment.project_id segment.iri_id segment.ensemble_id segment.decoupage_id segment.element_id %}"><img src="{{LDT_MEDIA_PREFIX}}img/annot_icon_80x45.png" width="80" height="45" /></a>
+                            <p class="duree_segment">{{ segment.duration }}</p>
+                        </div>
+                        <h4 class="title_segment"><a class="blue under" href="{% url ldt.ldt_utils.views.lignesdetemps.index_segment segment.project_id segment.iri_id segment.ensemble_id segment.decoupage_id segment.element_id %}">
+                          {% if segment.title %}{{ segment.title }}{% else %}{% trans "No title" %}{% endif %}</a></h4>
+                        <p class="text_segment">{% if segment.context %}{{ segment.context }}{% endif %}<br/>begin : {{ segment.begin|str_duration:"::" }} - dur : {{ segment.duration|str_duration:"::" }}</h4>
+                    </li>
+	                <!--li class="segmentinfos" ><span  class="" title="{% trans 'open ldt' %}"><a class="ldt_link_open_ldt" href="{% url ldt.ldt_utils.views.lignesdetemps.index_segment segment.project_id segment.iri_id segment.ensemble_id segment.decoupage_id segment.element_id %}"-->
+	                </li>
+                {% endfor %}
+                </ul>
+            </li>
+      {% endfor %}
+      {% endautoescape %}
+      <!-- Fin des médias -->
+      <!-- Pagination -->
+        <li id="result_pagination">
+            <p>
+            {% if results.has_previous %}
+	            <a class="blue under" href="{% url ldt.ldt_utils.views.front.search_listing %}?page={{ results.previous_page_number }}">{% trans "previous" %}</a>
+	        {% endif %}
+	        
+	        {% if results.paginator.num_pages > 1 %}
+	        <span class="current">
+	           {% blocktrans with number=results.number num_pages=results.paginator.num_pages%}Page {{number}} of {{num_pages}}{% endblocktrans %}
+	        </span>
+	        {% endif %}
+	
+	        {% if results.has_next %}
+	            <a class="blue under" href="{% url ldt.ldt_utils.views.front.search_listing %}?page={{ results.next_page_number }}">{% trans "next" %}</a>
+	        {% endif %}
+            </p>
+        </li>
+      <!-- Fin Pagination -->
+      </ul>
+    
+
+<!-- Right column -->
+<!-- APERÇU DU RÉSULTAT -->
+    <td id="result_preview">
+        <h4>ICI PREVIEW ?</h4>
+        <p class="bigmargin">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem …</p>
+    </td>
+  </tr>
+</table>
+
+  {% endifequal %}
+{% endif %}
+
+{% endblock %}
+
--- a/src/ldt/ldt/ldt_utils/urls.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/urls.py	Thu Jan 12 10:19:47 2012 +0100
@@ -43,6 +43,8 @@
     url(r'^front/$', 'views.front.front_home'),
     url(r'^front/group/(?P<group_id>.*)$', 'views.front.group_info'),
     url(r'^front/player/(?P<content_iri_id>.*)$', 'views.front.annot_content'),
+    url(r'^front/search/$', 'views.front.search_index'),
+    url(r'^front/searchListing', 'views.front.search_listing'),
 )
 
 urlpatterns += patterns('',
--- a/src/ldt/ldt/ldt_utils/views/front.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/front.py	Thu Jan 12 10:19:47 2012 +0100
@@ -7,15 +7,16 @@
 from django.template import RequestContext
 from guardian.shortcuts import get_objects_for_group
 from ldt.ldt_utils.models import Content, Project
+from ldt.ldt_utils.views.workspace import search_index as ws_search_index, search_listing as ws_search_listing
 from ldt.security.utils import add_change_attr
 
 
 @login_required
 def front_home(request):
     # Get the 3 last annotated contents
-    last_contents = Content.objects.all()[:3]
+    last_contents = Content.objects.order_by('-content_creation_date')[:3]
     # Get the most annotated contents
-    most_contents = Content.objects.all()[4:12]
+    most_contents = Content.objects.order_by('-nb_annotation')[:8]
     # Get the active groups
     active_groups = Group.objects.exclude(name=settings.PUBLIC_GROUP_NAME)[:5]
     
@@ -72,4 +73,14 @@
                               context_instance=RequestContext(request))
 
 
+@login_required
+def search_index(request):
+    return ws_search_index(request, front_template=True)
+
+
+@login_required
+def search_listing(request):
+    return ws_search_listing(request, front_template=True)
+
+
     
--- a/src/ldt/ldt/ldt_utils/views/workspace.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/ldt_utils/views/workspace.py	Thu Jan 12 10:19:47 2012 +0100
@@ -152,7 +152,7 @@
 
 
 @login_required
-def search_index(request):
+def search_index(request, front_template=False):
         
     sform = SearchForm(request.POST)
     if sform.is_valid():
@@ -167,7 +167,8 @@
         else:
             results = get_results_with_context(field, search)     
             complete_results = []
-            proj_list = Project.safe_objects.all()
+            # the search is made only on the published project
+            proj_list = Project.safe_objects.filter(state=2)
             results.sort(key=lambda k: k['iri_id'])
             for iri_id, item in groupby(results, itemgetter('iri_id')):                
                 try: 
@@ -192,7 +193,7 @@
                 
                 score = sum([seg['score'] for seg in segments])
                 desc = content.description if content.description else ''
-                complete_results.append({'list' : segments, 'score' : score, 'content_title' : content.title, 'content_id' : content.iri_id, 'content_description' : desc })
+                complete_results.append({'list' : segments, 'score' : score, 'content_title' : content.title, 'content_id' : content.iri_id, 'content_description' : desc, 'content':content })
             
             complete_results.sort(key=lambda k: k['score'])
                                 
@@ -210,15 +211,25 @@
                 
             results.object_list = highlight_documents(results.object_list, search, field)
             
-            return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))   
+            
+            if front_template :
+                return render_to_response('front/front_search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))
+            else :
+                return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))
         
     else:
-        return HttpResponseRedirect(reverse('ldt.ldt_utils.views.workspace.published_project'))
+        if front_template :
+            return HttpResponseRedirect(reverse('ldt.ldt_utils.views.front.front_home'))
+        else :
+            return HttpResponseRedirect(reverse('ldt.ldt_utils.views.workspace.published_project'))
         
 
-def search_listing(request):
+def search_listing(request, front_template=False):
     if not cache.get('complete_results_%s' % request.user.username):
-        return HttpResponseRedirect(reverse('ldt.ldt_utils.views.workspace.published_project'))
+        if front_template :
+            return HttpResponseRedirect(reverse('ldt.ldt_utils.views.front.front_home'))
+        else :
+            return HttpResponseRedirect(reverse('ldt.ldt_utils.views.workspace.published_project'))
      
     complete_results = cache.get('complete_results_%s' % request.user.username)
     search = cache.get('search_%s' % request.user.username)
@@ -238,7 +249,10 @@
     
     results.object_list = highlight_documents(results.object_list, search, field)
 
-    return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))   
+    if front_template :
+        return render_to_response('front/front_search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))
+    else :
+        return render_to_response('ldt/ldt_utils/search_results.html', {'results': results, 'nb_results' : paginator.count, 'search' : search, 'LDT_MEDIA_PREFIX': settings.LDT_MEDIA_PREFIX, 'colorurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/color.xml', 'i18nurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/pkg/i18n', 'language': language_code, 'baseurl': settings.LDT_MEDIA_PREFIX + 'swf/ldt/'}, context_instance=RequestContext(request))   
   
 
 
--- a/src/ldt/ldt/security/__init__.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/security/__init__.py	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,99 @@
+from django.conf import settings
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.auth.models import User
+from django.core.signals import request_started 
+
+try:
+    from threading import local
+except ImportError:
+    from django.utils._threading_local import local
+    
+_thread_locals = local()
+
+# The function that protect models is called on the first
+# HTTP request sent to the server (see function protect_models_request
+# in this file), and can not be called in this file directly 
+# because of circular import.
+#
+# To protect models from command line, use set_current_user(my_user)
+# and protect_models().
+
+_models_are_protected = False
+
+def get_current_user():
+    return getattr(_thread_locals, 'user', None)
+
+def set_current_user(user):
+    _thread_locals.user = user
+    
+def del_current_user():
+    del _thread_locals.user
+    
+def get_anonymous_user():
+    if hasattr(get_anonymous_user, 'anonymous_user'):
+        return get_anonymous_user.anonymous_user
+    
+    get_anonymous_user.anonymous_user = User.objects.get(id=settings.ANONYMOUS_USER_ID)
+    return get_anonymous_user.anonymous_user 
+
+def protect_models():
+    cls_list = get_models_to_protect()
+    if cls_list:
+        for cls in get_models_to_protect():
+                protect_model(cls)
+    
+    _models_are_protected = True   
+    
+def unprotect_models():
+    for cls in get_models_to_protect():
+            unprotect_model(cls)
+            
+    _models_are_protected = False
+
+def get_models_to_protect():
+    if hasattr(get_models_to_protect, 'cls_list'):
+        return get_models_to_protect.cls_list
+        
+    cls_list = []
+    for cls_name in settings.USE_GROUP_PERMISSIONS:
+        cls_type = ContentType.objects.get(model=cls_name.lower())
+        cls_list.append(cls_type.model_class())
+    get_models_to_protect.cls_list = cls_list
+        
+    return cls_list
+
+def protect_model(cls):  
+    
+    cls.old_save = cls.save
+    cls.old_delete = cls.delete
+    class_name = cls.__name__.lower()
+    cls.save = change_security(class_name)(cls.save)
+    cls.delete = change_security(class_name)(cls.delete)    
+    
+def unprotect_model(cls): 
+    if hasattr(cls, 'old_save'):
+        cls.save = cls.old_save 
+        cls.delete = cls.old_delete 
+        del cls.old_save    
+        del cls.old_delete
+        cls.safe_objects.user = None 
+        cls.safe_objects.check_perm = False
+        
+def change_security(cls_name):
+    def wrapper(func):
+        def wrapped(self, *args, **kwargs):  
+                        
+            if self.pk and not get_current_user().has_perm('change_%s' % cls_name, self):
+                raise AttributeError('User %s is not allowed to change object %s' % (get_current_user(), self))
+      
+            return func(self, *args, **kwargs)
+        return wrapped    
+    return wrapper
+
+
+def protect_models_request(sender, **kwargs):
+    if not _models_are_protected:
+        protect_models()
+
+request_started.connect(protect_models_request)
+
--- a/src/ldt/ldt/security/manager.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/security/manager.py	Thu Jan 12 10:19:47 2012 +0100
@@ -1,6 +1,6 @@
 from django.db.models import Manager
 from guardian.shortcuts import get_objects_for_user
-from utils import get_current_user
+from ldt.security import get_current_user, get_anonymous_user
 
 class SafeManager(Manager):
     use_for_related_fields = True
@@ -11,17 +11,21 @@
         self.check_perm = check_perm
 
     def get_query_set(self):
+        
         if not self.check_perm:
             return super(SafeManager, self).get_query_set()   
-                       
+      
         if not self.user:
-            self.user = get_current_user()
-            
+            self.user = get_current_user()            
+
         if not self.user:
             raise AttributeError("No user is attached to the current thread.")
         
+        if not self.user.is_authenticated():
+            self.user = get_anonymous_user()
+        
         perm_name = '%s.view_%s' % (self.model._meta.app_label, self.model.__name__.lower()) 
         
         user_objects = get_objects_for_user(self.user, perm_name, klass=self.model.objects) 
-            
+                    
         return user_objects
\ No newline at end of file
--- a/src/ldt/ldt/security/middleware.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/security/middleware.py	Thu Jan 12 10:19:47 2012 +0100
@@ -1,16 +1,14 @@
-from ldt.security.utils import protect_models, unprotect_models, _thread_locals, set_current_user, del_current_user
+from ldt.security import  set_current_user, del_current_user, _thread_locals
 
 class SecurityMiddleware(object):
     
     def process_request(self, request):
         if not hasattr(_thread_locals, 'user'):
             set_current_user(request.user)
-            protect_models()
     
     def process_response(self, request, response):
         
         if hasattr(_thread_locals, 'user'):            
-            unprotect_models()
             del_current_user()
                 
         return response
--- a/src/ldt/ldt/security/models.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/security/models.py	Thu Jan 12 10:19:47 2012 +0100
@@ -2,8 +2,8 @@
 from manager import SafeManager
 
 class SafeModel(models.Model):
-    objects = SafeManager()         # By default, SafeManagers do not chek permissions.
-    safe_objects = SafeManager()    # This setting is activated in the middleware
+    objects = SafeManager()        
+    safe_objects = SafeManager(check_perm=True)   
     
     class Meta:
         abstract = True
\ No newline at end of file
--- a/src/ldt/ldt/security/utils.py	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/security/utils.py	Thu Jan 12 10:19:47 2012 +0100
@@ -2,65 +2,9 @@
 from django.contrib.contenttypes.models import ContentType
 from guardian.shortcuts import assign, remove_perm, get_users_with_perms, get_groups_with_perms, get_objects_for_user
 from cache import get_cached_userlist
+from ldt.security import change_security 
 import types
-
-try:
-    from threading import local
-except ImportError:
-    from django.utils._threading_local import local
-    
-_thread_locals = local()
-
-def get_current_user():
-    return getattr(_thread_locals, 'user', None)
-
-def set_current_user(user):
-    _thread_locals.user = user
-    
-def del_current_user():
-    del _thread_locals.user
-    
-def protect_models():
-    cls_list = get_models_to_protect()
-    if cls_list:
-        user = get_current_user()
-        for cls in get_models_to_protect():
-                protect_model(cls, user)    
-    
-def unprotect_models():
-    for cls in get_models_to_protect():
-            unprotect_model(cls)
-
-def get_models_to_protect():
-    if hasattr(get_models_to_protect, 'cls_list'):
-        return get_models_to_protect.cls_list
-        
-    cls_list = []
-    for cls_name in settings.USE_GROUP_PERMISSIONS:
-        cls_type = ContentType.objects.get(model=cls_name.lower())
-        cls_list.append(cls_type.model_class())
-    get_models_to_protect.cls_list = cls_list
-        
-    return cls_list
-
-def protect_model(cls, user):   
-    cls.safe_objects.user = user
-    cls.safe_objects.check_perm = True
-    
-    cls.old_save = cls.save
-    cls.old_delete = cls.delete
-    class_name = cls.__name__.lower()
-    cls.save = change_security(class_name)(cls.save)
-    cls.delete = change_security(class_name)(cls.delete)    
-    
-def unprotect_model(cls): 
-    if hasattr(cls, 'old_save'):
-        cls.save = cls.old_save 
-        cls.delete = cls.old_delete 
-        del cls.old_save    
-        del cls.old_delete
-        cls.safe_objects.user = None 
-        
+  
 def unprotect_instance(instance):
     if hasattr(instance, 'old_save'):
         instance.save = instance.old_save
@@ -77,16 +21,6 @@
     delete = types.MethodType(change_security('project')(cls.delete), instance, cls)
     instance.delete = delete
         
-def change_security(cls_name):
-    def wrapper(func):
-        def wrapped(self, *args, **kwargs):  
-                        
-            if self.pk and not get_current_user().has_perm('change_%s' % cls_name, self):
-                raise AttributeError('User %s is not allowed to change object %s' % (get_current_user(), self))
-      
-            return func(self, *args, **kwargs)
-        return wrapped    
-    return wrapper
 
 def set_forbidden_stream(xml, user):
     cls = ContentType.objects.get(model='content')
--- a/src/ldt/ldt/static/ldt/css/front_common.css	Thu Jan 12 10:18:12 2012 +0100
+++ b/src/ldt/ldt/static/ldt/css/front_common.css	Thu Jan 12 10:19:47 2012 +0100
@@ -201,7 +201,7 @@
     position: relative; width: 378px; margin: 2px 0; height: 20px; border: 1px solid #000000; background: url(./imgs/search_icon.png) left no-repeat #ffffff;
 }
 
-#search_text {
+#id_search {
     position: absolute; top: 0; left: 25px; width: 250px; height: 20px; border: 0; padding: 0;
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ldt/ldt/templatetags/str_duration.py	Thu Jan 12 10:19:47 2012 +0100
@@ -0,0 +1,46 @@
+from django.template import Library, TemplateSyntaxError
+
+register = Library()
+
+@register.filter
+def str_duration(value, arg=None):
+    """Takes an integer value of milliseconds and write a human readable duration like 1h23, 01:23 (hours:minutes), 01:23:45 (hours:minutes:seconds), or number of seconds """
+    # Error management
+    if value is None :
+        return ""
+    if not isinstance(value, (int,long,float,str,unicode)) :
+        raise TemplateSyntaxError('str_duration value error : value must be integer or long or float or string. type = ' + str(type(value)))
+    if isinstance(value, (str,unicode)) :
+        try:
+            value = int(value)
+        except :
+            raise TemplateSyntaxError('str_duration value error : can not convert value "' + value + '" into integer')
+    # We take off the milliseconds
+    ms = abs(value)
+    sec = ms//1000
+    if arg is None :
+        arg = "::"
+    if arg=="::" or arg=="h" or arg==":" :
+        hours = sec//3600
+        min = (sec - (hours * 3600))//60
+        if min<10:
+            min_str = "0" + str(min)
+        else:
+            min_str = str(min)
+        if (arg=="::" or arg==":") and hours<10 :
+            hours_str = "0" + str(hours)
+        else :
+            hours_str = str(hours)
+        if arg=="h" or arg==":" :
+            return hours_str + arg + min_str
+        sec = (sec - (hours * 3600) - (min*60))
+        if sec<10:
+            sec_str = "0" + str(sec)
+        else:
+            sec_str = str(sec)
+        return hours_str + ":" + min_str + ":" + sec_str
+    elif arg=="s" :
+        return sec
+    else :
+        raise TemplateSyntaxError('str_duration filter error : filters argument must be None, "::", ":", "h" or "s"')
+str_duration.is_safe = True