--- a/src/spel/static/spel/js/spectacle.js Fri Mar 21 11:22:42 2014 +0100
+++ b/src/spel/static/spel/js/spectacle.js Fri Mar 21 15:21:15 2014 +0100
@@ -297,7 +297,10 @@
$('.annotation-results > div.searched-annot:visible').each(function(index){
bla.push({data: $(this).attr("data-start"), iri_id: $(this).attr("data-content") });
});
- if(bla.length==0){ return; }
+ if(bla.length==0){
+ $(".chapter-results").removeClass("loader");
+ return;
+ }
$.post(
urlChapters,
{
@@ -313,5 +316,38 @@
$(".chapter-results").html('<p class="bg-danger">Erreur de chargement</p>');
});
});
+
+ // Chapter to annotations management
+ $(".chapter-results").on("click", ".chapter-to-annot", function(){
+ // First we unselect chapter filters
+ $('option', $('#mulsel4')).each(function(element) { $(this).removeAttr('selected').prop('selected', false); });
+ $('#mulsel4').multiselect('refresh');
+ // Then we request
+ $(".annot-results").html("<br/><br/>");
+ $(".annot-results").addClass("loader");
+ var bla = [];
+ $('.chapter-data').each(function(index){
+ bla.push({start: $(this).attr("data-start"), end: $(this).attr("data-end"), iri_id: $(this).attr("data-content") });
+ });
+ if(bla.length==0){
+ $(".annotation-results").removeClass("loader");
+ return;
+ }
+ $.post(
+ urlAnnotations,
+ {
+ chapters: JSON.stringify(bla),
+ csrfmiddlewaretoken: csrf_token
+ },
+ function( html ) {
+ $(".annotation-results").removeClass("loader");
+ $(".annotation-results").html(html);
+ }
+ )
+ .fail(function() {
+ $(".annotation-results").removeClass("loader");
+ $(".annotation-results").html('<p class="bg-danger">Erreur de chargement</p>');
+ });
+ });
});
--- a/src/spel/templates/partial/spel_annotations.html Fri Mar 21 11:22:42 2014 +0100
+++ b/src/spel/templates/partial/spel_annotations.html Fri Mar 21 15:21:15 2014 +0100
@@ -1,6 +1,9 @@
{% load static %}
{% load front_tags %}
{% load spel_tags %}
+{% if chapter_annots %}
+<p class="btn-info info">Annotations correspondant aux chapitres :</p>
+{% endif %}
<div class="row">
<div class="col-md-8">
<ul class="list-inline annot-tag-list">
@@ -9,9 +12,11 @@
</ul>
<p><span class="nb-annotations-found">{{ nb_annotations }}</span> annotation(s) trouvée(s) sur {{ nb_contents }} vidéo(s)</p>
</div>
+ {% if not chapter_annots %}
<div class="col-md-4">
- <button class="annot-to-chapter btn btn-primary multiline btn-sm">Chapitres correspondant aux annotations</button>
+ <button class="annot-to-chapter btn btn-primary multiline btn-xs">Chapitres correspondant aux annotations</button>
</div>
+ {% endif %}
</div>
{% for res in results %}
{% for s in res.list %}
--- a/src/spel/templates/partial/spel_chapters.html Fri Mar 21 11:22:42 2014 +0100
+++ b/src/spel/templates/partial/spel_chapters.html Fri Mar 21 15:21:15 2014 +0100
@@ -4,19 +4,29 @@
{% if annot_chapters %}
<p class="bg-primary info">Chapitres correspondant aux annotations :</p>
{% endif %}
-<ul class="list-inline chapter-tag-list">
- {% 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 %}
-</ul>
-<p>{{ segments|length }} segment(s) trouvé(s)</p>
+<div class="row">
+ <div class="col-md-8">
+ <ul class="list-inline chapter-tag-list">
+ {% 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 %}
+ </ul>
+ <p>{{ segments|length }} segment(s) trouvé(s)</p>
+ </div>
+ {% if not annot_chapters %}
+ <div class="col-md-4">
+ <button class="chapter-to-annot btn btn-info multiline btn-xs">Annotations correspondant aux chapitres</button>
+ </div>
+ {% endif %}
+</div>
<table class="table table-striped table-condensed tablesorter">
<thead>
<tr><th>Type</th><th>Ref texte</th><th>Titre de la vidéo</th><th> </th></tr>
</thead>
<tbody>
{% for s in segments %}
- <tr><td>{{ s.cutting_id }}</td><td>{{ s.tags|get_tags:"ref_text"|join:', ' }}</td><td>{% if annot_chapters %}{{ s.ct }}{% else %}{{ s.content.title }}{% endif %}</td>
+ <tr class="chapter-data" data-content="{{ s.iri_id }}" data-start="{{ s.start_ts }}" data-end="{{ s.start_ts|add:s.duration }}">
+ <td>{{ s.cutting_id }}</td><td>{{ s.tags|get_tags:"ref_text"|join:', ' }}</td><td>{% if annot_chapters %}{{ s.ct }}{% else %}{{ s.content.title }}{% endif %}</td>
<td>
<button type="button" class="popinfo btn btn-xs btn-default" 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 }}<br/>{{ s.tags|get_tags:'group'|safe }}"><span class="glyphicon glyphicon-plus-sign"></span></button>
--- a/src/spel/views.py Fri Mar 21 11:22:42 2014 +0100
+++ b/src/spel/views.py Fri Mar 21 15:21:15 2014 +0100
@@ -179,6 +179,71 @@
context = {"q":q, "searched_tags": type_inter_param.split(","), "results": results, "nb_contents": nb_contents, "nb_annotations": nb_segments}
return self.render_to_response(context)
+
+ def post(self, request):
+ chapters_param = request.POST.get("chapters", "[]")
+ grouped_chapters = []
+ for iri_id, items in groupby(json.loads(chapters_param), itemgetter('iri_id')):
+ # Get segments timecodes
+ s = [ {"start": int(i["start"]), "end": int(i["end"])} for i in items ]
+ grouped_chapters.append({ 'content': iri_id, 'list': s })
+ if len(grouped_chapters)==0:
+ return HttpResponse("")
+
+
+ # Request segment : we make a complex query impossible (?) to do with orm, even with Q, Sum and other stuffs.
+ # Here is a SQL example of what we want :
+ # select *
+ # from ldt_utils_segment
+ # where cutting_id IN ('performance','discussion')
+ # AND (
+ # ( ldt_utils_segment.iri_id='CONTENT_ID_1' AND (
+ # ( TIMECODE_START_1 < ldt_utils_segment.start_ts AND ldt_utils_segment.start_ts < TIMECODE_END_1 )
+ # OR
+ # ( TIMECODE_START_2 < ldt_utils_segment.start_ts AND ldt_utils_segment.start_ts < TIMECODE_END_2 )
+ # ))
+ # OR
+ # ( ldt_utils_segment.iri_id='CONTENT_ID_2' AND (
+ # ( TIMECODE_START_3 < ldt_utils_segment.start_ts AND ldt_utils_segment.start_ts < TIMECODE_END_3 )
+ # ))
+ # )
+
+ raw_query = "select id, iri_id, cutting_id, tags, start_ts, duration, title, abstract \nfrom ldt_utils_segment \nwhere cutting_id NOT IN ('performance','discussion') \nAND ("
+ for i, ga in enumerate(grouped_chapters):
+ if i>0:
+ raw_query += "\n OR "
+ raw_query += "\n ( ldt_utils_segment.iri_id='" + ga["content"] + "' AND ("
+ for j, tc in enumerate(ga["list"]):
+ if j>0:
+ raw_query += "\n OR "
+ raw_query += "\n ( " + str(tc["start"]) + " < ldt_utils_segment.start_ts AND ldt_utils_segment.start_ts < " + str(tc["end"]) + " )"
+ raw_query += "\n )) "
+ raw_query += "\n)"
+
+ # Dict because of itemgetter for groupby
+ tagged_segs = [ dict(s.__dict__) for s in Segment.objects.raw(raw_query) ]
+ for i in tagged_segs:
+ i["tags"] = i["_tags_cache"] # WHY ????? Because i don't know but we need it
+ # Prefetch all contents
+ all_contents = list(Content.objects.filter(iri_id__in=[s['iri_id'] for s in tagged_segs]))
+ results = []
+ for iri_id, items in groupby(tagged_segs, itemgetter('iri_id')):
+ # Get good content
+ content = None
+ content_filter = filter(lambda e: e.iri_id == iri_id, all_contents)
+ if len(content_filter)>0:
+ content = content_filter[0]
+ if content is None:
+ continue
+ # Get segments
+ s = list(items)
+ results.append({ 'content': content, 'list': s })
+ nb_contents = len(results)
+ nb_segments = len(tagged_segs)
+
+ context = {"chapter_annots":True, "q":"", "searched_tags": [], "results": results, "nb_contents": nb_contents, "nb_annotations": nb_segments}
+
+ return self.render_to_response(context)