v0.5.11 opera requests work V00.05.11
authorcavaliet
Thu, 15 May 2014 17:55:50 +0200
changeset 91 1f24f33b41e1
parent 90 bc700c2cd9f3
child 92 23ab1d3bbe7a
v0.5.11 opera requests work
src/spel/__init__.py
src/spel/static/spel/css/spel.css
src/spel/static/spel/js/opera.js
src/spel/templates/partial/spel_opera_annotations.html
src/spel/templates/spel_opera.html
src/spel/templates/spel_theatre.html
src/spel/templatetags/spel_tags.py
src/spel/urls.py
src/spel/views.py
--- a/src/spel/__init__.py	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/__init__.py	Thu May 15 17:55:50 2014 +0200
@@ -1,4 +1,4 @@
-VERSION = (0, 5, 10, "final", 0)
+VERSION = (0, 5, 11, "final", 0)
 
 VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION[:2])))
 
--- a/src/spel/static/spel/css/spel.css	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/static/spel/css/spel.css	Thu May 15 17:55:50 2014 +0200
@@ -19,7 +19,7 @@
 .width100percent{
   width: 100%;
 }
-.spel-content > .row > .chapters > .row{
+.filter-row{
 	margin-bottom: 10px;
 }
 .toggle-text{
--- a/src/spel/static/spel/js/opera.js	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/static/spel/js/opera.js	Thu May 15 17:55:50 2014 +0200
@@ -7,7 +7,7 @@
 	    },
 	    onChange: function(element, checked) {
 	      var filter_enabled = false;
-	      var chbs = $(".chapters input:checkbox");
+	      var chbs = $(".spel-content input:checkbox");
 	      for (var i = chbs.length - 1; i >= 0; i--) {
 	        filter_enabled = filter_enabled || $(chbs[i]).is(":checked");
 	      };
@@ -19,14 +19,6 @@
 	      }
 	    }
 	});
-	// Annotations multiselect management
-	$('.annotations .multiselect').multiselect({
-	    buttonText: function(options, select) {
-	      return $(select).attr("data-title") + ' (' + options.length + ') <b class="caret"></b>';
-	    },
-	    buttonContainer: '<div class="btn-group width100percent" />',
-	    buttonClass: 'btn btn-default width100percent disabled'
-	});
 
 	// Data 1
 	var data1 = [
@@ -74,7 +66,7 @@
 		var n = data.objects.length;
 		var data4 = [];
 		for(var i=0;i<n;i++){
-			data4.push({label: o[i].name.substr(20), value: o[i].name.substr(12)});
+			data4.push({label: o[i].name.substr(20), value: o[i].name});
 		}
 		$("#mulsel4").multiselect('dataprovider', data4);
 		$("#mulsel4").multiselect('enable');
@@ -97,11 +89,11 @@
         var n = data.objects.length;
         var data5 = [];
         for(var i=0;i<n;i++){
-            data5.push({label: parseInt(o[i].name.substr(12)), value: parseInt(o[i].name.substr(12))});
+            data5.push({label: parseInt(o[i].name.substr(12)), value: o[i].name});
         }
         // Sort
         data5.sort(function(a,b){
-            return a.value - b.value;
+            return a.label - b.label;
         });
         $("#mulsel5").multiselect('dataprovider', data5);
         $("#mulsel5").multiselect('enable');
@@ -116,17 +108,17 @@
         var n = data.objects.length;
         var data6 = [];
         for(var i=0;i<n;i++){
-            data6.push({label: parseInt(o[i].name.substr(13)), value: parseInt(o[i].name.substr(13))});
+            data6.push({label: parseInt(o[i].name.substr(13)), value: o[i].name});
         }
         // Sort
         data6.sort(function(a,b){
-            return a.value - b.value;
+            return a.label - b.label;
         });
         $("#mulsel6").multiselect('dataprovider', data6);
         $("#mulsel6").multiselect('enable');
     });
     
-    // Data 6 : Mesure
+    // Data 7 : Mesure
     $.ajax({
         url: urlOM
     })
@@ -135,12 +127,12 @@
         var n = data.objects.length;
         var data7 = [];
         for(var i=0;i<n;i++){
-            data7.push({label: o[i].name.substr(14), value: o[i].name.substr(14)});
+            data7.push({label: o[i].name.substr(14), value: o[i].name});
         }
         // Sort
         data7.sort(function(a,b){
-            var v1 = parseInt(a.value.split(" ")[0]);
-            var v2 = parseInt(b.value.split(" ")[0]);
+            var v1 = parseInt(a.label.split(" ")[0]);
+            var v2 = parseInt(b.label.split(" ")[0]);
             if(isNaN(v1) || isNaN(v2)){
                 return false;
             }
@@ -169,20 +161,24 @@
 	
 	// Search chapters management
 	$("#btn-filter-chapters").click(function(e){
-		if($("#mulsel1").val()==null && $("#mulsel2").val()==null && $("#mulsel3").val()==null){
+		if($("#mulsel1").val()==null && $("#mulsel2").val()==null && $("#mulsel3").val()==null && $("#mulsel4").val()==null && $("#mulsel5").val()==null && $("#mulsel6").val()==null && $("#mulsel7").val()==null){
 			$(".chapter-results").html("<p>Vous devez sélectionner au moins un filtre</p>");
 			return false;
 		}
 		$(".chapter-results").html("<br/><br/>");
 		$(".chapter-results").addClass("loader");
 		$.ajax({
-			url: urlChapters,
+			url: urlAnnotations,
 			data:{
 				start_date: $('input[name=start_date]').val(),
 				end_date: $('input[name=end_date]').val(),
 				annotation_types: ( ($("#mulsel1").val()==null) ? [] : $("#mulsel1").val() ).join(","),
 				modalites_sceniques: ( ($("#mulsel2").val()==null) ? [] : $("#mulsel2").val() ).join(","),
 				personnages: ( ($("#mulsel3").val()==null) ? [] : $("#mulsel3").val() ).join(","),
+				type_travail: ( ($("#mulsel4").val()==null) ? [] : $("#mulsel4").val() ).join(","),
+				acte: ( ($("#mulsel5").val()==null) ? [] : $("#mulsel5").val() ).join(","),
+				scene: ( ($("#mulsel6").val()==null) ? [] : $("#mulsel6").val() ).join(","),
+				mesure: ( ($("#mulsel7").val()==null) ? [] : $("#mulsel7").val() ).join(","),
 				start_text: $("#start-text").val(),
 				end_text: $("#end-text").val()
 			}
@@ -204,11 +200,23 @@
 			$("#mulsel1").multiselect('deselect', $(this).parent().text().trim());
 		}
 		else if($(this).parent().hasClass("modscen")){
-			$("#mulsel2").multiselect('deselect', "modalites_sceniques: " + $(this).parent().text().trim());
+			$("#mulsel2").multiselect('deselect', "opera_modalites_sceniques: " + $(this).parent().text().trim());
 		}
 		else if($(this).parent().hasClass("perso")){
-			$("#mulsel3").multiselect('deselect', "personnages: " + $(this).parent().text().trim());
+			$("#mulsel3").multiselect('deselect', "opera_personnages: " + $(this).parent().text().trim());
 		}
+        else if($(this).parent().hasClass("type-travail")){
+            $("#mulsel4").multiselect('deselect', "opera_type_travail: " + $(this).parent().text().trim());
+        }
+        else if($(this).parent().hasClass("acte")){
+            $("#mulsel5").multiselect('deselect', "opera_acte: " + $(this).parent().text().split(" ")[1].trim());
+        }
+        else if($(this).parent().hasClass("scene")){
+            $("#mulsel6").multiselect('deselect', "opera_scene: " + $(this).parent().text().split(" ")[1].trim());
+        }
+        else if($(this).parent().hasClass("mesure")){
+            $("#mulsel7").multiselect('deselect', "opera_mesure: " + $(this).parent().text().split(" ")[1].trim());
+        }
 		else if($(this).parent().hasClass("date")){
 			$('input[name=start_date]').val("");
 			$('input[name=end_date]').val("");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/spel/templates/partial/spel_opera_annotations.html	Thu May 15 17:55:50 2014 +0200
@@ -0,0 +1,46 @@
+{% load static %}
+{% load front_tags %}
+{% load spel_tags %}
+<div class="row">
+  <div class="col-md-8">
+	<ul class="list-inline chapter-tag-list">
+	    {% if start_date != "" or end_date != "" %}<li class="small searched-tag date">
+	      {% if start_date != "" %}{{ start_date }} &le; {% endif %}date{% if end_date != "" %} &le; {{ end_date }}{% endif %}
+	      <span class="glyphicon glyphicon-remove small"></span></li>
+	    {% endif %}
+	    {% for t in annot_types %}<li class="small searched-tag type">{{ t|remove_tag_key }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	    {% for t in mod_scen %}<li class="small searched-tag modscen">{{ t|remove_tag_key }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	    {% for t in perso %}<li class="small searched-tag perso">{{ t|remove_tag_key }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	    {% for t in type_travail %}<li class="small searched-tag type-travail">{{ t|remove_tag_key }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	    {% for t in acte %}<li class="small searched-tag acte">{{ t|remove_opera }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	    {% for t in scene %}<li class="small searched-tag scene">{{ t|remove_opera }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	    {% for t in mesure %}<li class="small searched-tag mesure">{{ t|remove_opera }} <span class="glyphicon glyphicon-remove small"></span></li>{% endfor %}
+	</ul>
+    <p>{{ segments|length }} segment(s) trouvé(s)</p>
+  </div>
+</div>
+<table class="table table-striped table-condensed tablesorter">
+    <thead>
+        <tr><th>Type</th><th>Titre de la vidéo</th><th>Modalités scéniques</th><th>Personnages</th><th>Travail</th><th>Acte</th><th>Scène</th><th>Mesure</th><th class="popinfo">&nbsp;</th></tr>
+    </thead>
+    <tbody>
+  {% for s in segments %}
+    <tr class="chapter-data" data-content="{{ s.iri_id }}" data-start="{{ s.start_ts }}" data-end="{{ s.start_ts|add:s.duration }}">
+        <td title="{{ s.cutting_id }}">{{ s.cutting_id|slice:":1"|upper }}</td>
+        <td>{% if annot_chapters %}{{ s.ct }}{% else %}{{ s.content.title }}{% endif %}</td>
+        <td>{{ s.tags|get_tags:"opera_modalites_sceniques"|join:', ' }}</td>
+        <td>{{ s.tags|get_tags:"opera_personnages"|join:', ' }}</td>
+        <td>{{ s.tags|get_tags:"opera_type_travail"|join:', ' }}</td>
+        <td>{{ s.tags|get_tags:"opera_acte"|join:', ' }}</td>
+        <td>{{ s.tags|get_tags:"opera_scene"|join:', ' }}</td>
+        <td>{{ s.tags|get_tags:"opera_mesure"|join:', ' }}</td>
+        <td>
+          <span class="glyphicon glyphicon-info-sign popinfo" data-trigger="hover" data-container="body" data-toggle="popover" data-placement="auto" 
+                  data-content="<strong>Timecodes:</strong> {{ s.start_ts|str_duration }} - {{ s.start_ts|add:s.duration|str_duration }}"></span>
+          <a class="play-button" href="{% url 'spel_player' %}?g={{ s.iri_id }}&d=opera&f=original_web.mp4#id={{ s.element_id }}" target="_blank"><span class="glyphicon glyphicon-play"></span></a>
+          <input type="checkbox" class="filter-chapter-annot" />
+        </td>
+    </tr>
+  {% endfor %}
+    <tbody>
+</table>
--- a/src/spel/templates/spel_opera.html	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/templates/spel_opera.html	Thu May 15 17:55:50 2014 +0200
@@ -13,7 +13,7 @@
 
 {% block spel_content %}
       <h3>Page Opéra</h3>
-      <div class="row">
+      <div class="row filter-row">
           <div class="col-md-4">
             <select id="mulsel1" class="multiselect" multiple="multiple" data-title="Types de chapitres"></select>
           </div>
@@ -25,7 +25,7 @@
             <input type="text" class="input-sm form-control" name="end_date" />
           </div>
       </div>
-      <div class="row">
+      <div class="row filter-row">
         <div class="col-md-4">
           <select id="mulsel2" class="multiselect" multiple="multiple" data-title="Modalités scéniques" disabled="disabled"></select>
         </div>
@@ -36,7 +36,7 @@
           <select id="mulsel4" class="multiselect" multiple="multiple" data-title="Type travail" disabled="disabled"></select>
         </div>
       </div>
-      <div class="row">
+      <div class="row filter-row">
         <div class="col-md-4">
           <select id="mulsel5" class="multiselect" multiple="multiple" data-title="Actes" disabled="disabled"></select>
         </div>
@@ -47,9 +47,10 @@
           <select id="mulsel7" class="multiselect" multiple="multiple" data-title="Mesures" disabled="disabled"></select>
         </div>
       </div>
-      <div class="row">
-        <div class="annotation-results">Résultats d'annotations</div>
+      <div class="row filter-row text-center">
+        <button id="btn-filter-chapters" class="btn btn-success" disabled="disabled">FILTRER</button>
       </div>
+      <div class="chapter-results">Résultats d'annotations</div>
 {% endblock %}
 {% block page_js %}
   <script type="text/javascript" src="{% static 'spel/lib/jquery.min.js' %}"></script>
@@ -68,7 +69,7 @@
   var urlOS = "{% url 'api_dispatch_list' resource_name='tags' api_name='1.0' %}?format=json&limit=500&name__startswith=opera_scene:&order_by=name";
   var urlOM = "{% url 'api_dispatch_list' resource_name='tags' api_name='1.0' %}?format=json&limit=500&name__startswith=opera_mesure&order_by=name";
   //var urlChapters = "{% url 'spel_chapters' %}";
-  //var urlAnnotations = "{% url 'spel_annotations' %}";
+  var urlAnnotations = "{% url 'spel_opera_annotations' %}";
   var csrf_token = "{{csrf_token}}";
   $('.input-daterange').datepicker({
 	    format: "yyyy-mm-dd",
--- a/src/spel/templates/spel_theatre.html	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/templates/spel_theatre.html	Thu May 15 17:55:50 2014 +0200
@@ -16,7 +16,7 @@
       <div class="row">
         <div class="col-md-6 chapters">
           <h4 class="text-center">CHAPITRES</h4>
-          <div class="row">
+          <div class="row filter-row">
             <div class="col-md-4">Dates de répétition :</div>
             <div class="col-md-7 input-daterange input-group">
               <span class="input-group-addon">de</span>
@@ -25,7 +25,7 @@
 		      <input type="text" class="input-sm form-control" name="end_date" />
 		    </div>
 		  </div>
-          <div class="row">
+          <div class="row filter-row">
             <div class="col-md-4">
               <select id="mulsel1" class="multiselect" multiple="multiple" data-title="Types de chapitres">
               </select>
@@ -39,13 +39,13 @@
               </select>
             </div>
           </div>
-          <div class="row toggle-text"><span class="glyphicon glyphicon-chevron-right"></span> Voir les références de textes</div>
-          <div class="row theatre-text" style="display: none;">
+          <div class="row filter-row toggle-text"><span class="glyphicon glyphicon-chevron-right"></span> Voir les références de textes</div>
+          <div class="row filter-row theatre-text" style="display: none;">
             <iframe src="{% url 'spel_ctb' %}" width="97%" height="150px"></iframe>
             <span>Début : </span><select id="start-text"></select>
             <span>Fin : </span><select id="end-text"></select>
           </div>
-          <div class="row text-center">
+          <div class="row filter-row text-center">
             <button id="btn-filter-chapters" class="btn btn-success" disabled="disabled">FILTRER</button>
           </div>
           <div class="chapter-results"></div>
--- a/src/spel/templatetags/spel_tags.py	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/templatetags/spel_tags.py	Thu May 15 17:55:50 2014 +0200
@@ -38,7 +38,7 @@
                 continue
             if t[:t.index(":")]=="modalites_sceniques" or t[:t.index(":")]=="personnages":
                 val.append(t[t.index(":")+2:])
-    elif arg in ["type_inter", "personnages", "ref_text"]:
+    elif arg in ["type_inter", "personnages", "ref_text", "opera_modalites_sceniques", "opera_personnages", "opera_type_travail", "opera_acte", "opera_scene", "opera_mesure"]:
         for t in a:
             try:
                 t.index(":")
@@ -83,3 +83,16 @@
     return value[value.index(":")+2:]
 remove_tag_key.is_safe = True
 
+@register.filter
+def remove_opera(value):
+    """ Takes a string as 'opera_key: value' and returns the 'key: value' """
+    # Error management
+    if value is None :
+        return ""
+    if not isinstance(value, (str,unicode)) :
+        raise TemplateSyntaxError('remove_tag_key value error : string is required')
+    if value[:6]=="opera_":
+        return value[6:]
+    return value
+remove_tag_key.is_safe = True
+
--- a/src/spel/urls.py	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/urls.py	Thu May 15 17:55:50 2014 +0200
@@ -6,7 +6,7 @@
 from django.views.generic import RedirectView, TemplateView
 from ldt.auth.views import login as pf_login
 from ldt.text import VERSION_STR
-from .views import AnnotationRequest, ChapterRequest, Theatre, Opera
+from .views import AnnotationRequest, ChapterRequest, Theatre, Opera, OperaRequest
 
 #from django.conf import settings
 
@@ -45,12 +45,13 @@
     (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
     url(r'^$', TemplateView.as_view(template_name="spel_home.html"), name='spel_home'),
     url(r'^theatre$', Theatre.as_view(), name='spel_theatre'),
-    url(r'^opera$', Opera.as_view(), name='spel_opera'),
     url(r'^chapters$', ChapterRequest.as_view(), name='spel_chapters'),
     url(r'^annotations', AnnotationRequest.as_view(), name='spel_annotations'),
     url(r'^ctb', TemplateView.as_view(template_name="ctb.html"), name='spel_ctb'),
     url(r'^corpus', TemplateView.as_view(template_name="spel_corpus.html"), name='spel_corpus'),
     url(r'^player', TemplateView.as_view(template_name="spel_player.html"), name='spel_player'),
+    url(r'^opera$', Opera.as_view(), name='spel_opera'),
+    url(r'^operaannotations$', OperaRequest.as_view(), name='spel_opera_annotations'),
 )
 
 urlpatterns += staticfiles_urlpatterns()
--- a/src/spel/views.py	Thu May 15 15:29:21 2014 +0200
+++ b/src/spel/views.py	Thu May 15 17:55:50 2014 +0200
@@ -337,7 +337,79 @@
         return self.render_to_response(context)
 
 
-
+class OperaRequest(TemplateView):
+    
+    template_name = "partial/spel_opera_annotations.html"
+    
+    def get(self, request):
+        # Filter content by date if necessary
+        content_qs = Content.objects.filter(tags__name__in=["content_opera"])
+        start_date_param = request.GET.get("start_date", "")
+        if start_date_param!="":
+            content_qs = content_qs.filter(content_creation_date__gt=start_date_param)
+        end_date_param = request.GET.get("end_date", "")
+        if end_date_param!="":
+            content_qs = content_qs.filter(content_creation_date__lt=end_date_param + " 23:59:59")
+        iri_ids = content_qs.values_list("iri_id", flat=True)
+        #logger.debug("iri_ids")
+        #logger.debug(iri_ids)
+        # Filter segment if necessary
+        annot_types_param = request.GET.get("annotation_types", "")
+        seg_queryset = Segment.objects.filter(iri_id__in=iri_ids).select_related("content__title")
+        annot_types = []
+        if annot_types_param!="":
+            annot_types = annot_types_param.split(",")
+            seg_queryset = seg_queryset.filter(cutting_id__in=annot_types)
+        
+        # First we look at modalites_sceniques and personnages tags.
+        mod_scen_param = request.GET.get("modalites_sceniques", "")
+        mod_scen = []
+        if mod_scen_param!="":
+            mod_scen = mod_scen_param.split(",")
+        perso_param = request.GET.get("personnages", "")
+        perso = []
+        if perso_param!="":
+            perso = perso_param.split(",")
+        type_travail_param = request.GET.get("type_travail", "")
+        type_travail = []
+        if type_travail_param!="":
+            type_travail = type_travail_param.split(",")
+        acte_param = request.GET.get("acte", "")
+        acte = []
+        if acte_param!="":
+            acte = acte_param.split(",")
+        scene_param = request.GET.get("scene", "")
+        scene = []
+        if scene_param!="":
+            scene = scene_param.split(",")
+        mesure_param = request.GET.get("mesure", "")
+        mesure = []
+        if mesure_param!="":
+            mesure = mesure_param.split(",")
+        
+        
+        
+        # Get tags from orm
+        all_tags = mod_scen + perso + type_travail + acte + scene + mesure
+        tags = Tag.objects.filter(name__in=all_tags)
+        # seg_queryset.filter(tags__in=tags) doesn't work because taggit finds segments with one of the tags and not ALL tags
+        # So we make a correct request through TaggedItem first
+        # Get segments from tagged items
+        #s = TaggedItem.objects.get_by_model(seg_queryset, tags)
+        tags = list(tags)
+        seg_ids = list(TaggedItem.objects\
+                    .values_list("object_id", flat=True)\
+                    .filter(content_type=ContentType.objects.get_for_model(Segment))\
+                    .filter(tag__in=tags)\
+                    .annotate(count_status=Count('object_id'))\
+                    .filter(count_status=len(tags)))
+        s = list(seg_queryset.filter(pk__in=seg_ids))
+        
+        context = {"annot_types":annot_types, "start_date":start_date_param, "end_date":end_date_param, 
+                   "mod_scen":mod_scen, "perso":perso, "type_travail":type_travail, "acte":acte, 
+                   "scene":scene, "mesure":mesure, "segments": s}
+        
+        return self.render_to_response(context)