Modified CurrentSegmentInfobox to allow for editable segments (title, description and tags)
authordurandn
Fri, 28 Aug 2015 12:24:30 +0200
changeset 79 fd48103c0deb
parent 78 3926ac9e5c77
child 80 774398426834
Modified CurrentSegmentInfobox to allow for editable segments (title, description and tags)
server/src/remie/static/remie/metadataplayer/CurrentSegmentInfobox.css
server/src/remie/static/remie/metadataplayer/CurrentSegmentInfobox.js
--- a/server/src/remie/static/remie/metadataplayer/CurrentSegmentInfobox.css	Fri Aug 28 11:52:42 2015 +0200
+++ b/server/src/remie/static/remie/metadataplayer/CurrentSegmentInfobox.css	Fri Aug 28 12:24:30 2015 +0200
@@ -39,10 +39,90 @@
 	font-weight: bold;
 }
 
+textarea.Ldt-CurrentSegmentInfobox-DescriptionInput.Ldt-CurrentSegmentInfobox-Description{
+	display: inline-block;
+	width: 95%;
+}
+
 .Ldt-CurrentSegmentInfobox-Tags{
 }
 
 .Ldt-CurrentSegmentInfobox-NoSegment{
 	font-size: 15px;
 	font-weight: bold;
+}
+
+.Ldt-CurrentSegmentInfobox-SubmitButton{
+	display: inline-block;
+    background-color: #d93c71;
+    color: #ffffff;
+    float: right;
+    cursor: pointer;
+    height: 14px;
+    width: 100px;
+    margin: 2px;
+    margin-top: 5px;
+    padding: 2px;
+    font-size: 11px;
+    border: 1px solid;
+    border-color: #eca3bc #631e34 #36101c #e16e93;
+    cursor: pointer;
+    text-align: center;
+    vertical-align: middle;
+}
+
+.Ldt-CurrentSegmentInfobox-CancelButton{
+	display: inline-block;
+    background-color: #d93c71;
+    color: #ffffff;
+    float: right;
+    cursor: pointer;
+    height: 14px;
+    width: 100px;
+    margin: 2px;
+    margin-top: 5px;
+    margin-right: 5px;
+    padding: 2px;
+    font-size: 11px;
+    border: 1px solid;
+    border-color: #eca3bc #631e34 #36101c #e16e93;
+    cursor: pointer;
+    text-align: center;
+    vertical-align: middle;
+}
+
+.Ldt-CurrentSegmentInfobox-CreateTagButton{
+	display: block;
+    background-color: #d93c71;
+    color: #ffffff;
+    cursor: pointer;
+    height: 14px;
+    width: 75px;
+    margin: 2px;
+    padding: 2px;
+    font-size: 11px;
+    border: 1px solid;
+    border-color: #eca3bc #631e34 #36101c #e16e93;
+    cursor: pointer;
+    text-align: center;
+    vertical-align: middle;
+}
+
+.Ldt-CurrentSegmentInfobox-Tags-Li-Input{
+	width: 80px;
+}
+
+.Ldt-CurrentSegmentInfobox-CreateTagButton:hover, .Ldt-CurrentSegmentInfobox-CancelButton:hover,
+.Ldt-CurrentSegmentInfobox-SubmitButton:hover{
+	background-color: #e15581;
+	border-color: #222222 #e87d9f #f0adc3 #68273c;
+}
+
+.Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton{
+	font-weight: bold;
+	color: #d93c71
+}
+
+.Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton:hover{
+	color: #e16e93
 }
\ No newline at end of file
--- a/server/src/remie/static/remie/metadataplayer/CurrentSegmentInfobox.js	Fri Aug 28 11:52:42 2015 +0200
+++ b/server/src/remie/static/remie/metadataplayer/CurrentSegmentInfobox.js	Fri Aug 28 12:24:30 2015 +0200
@@ -8,48 +8,79 @@
 
 IriSP.Widgets.CurrentSegmentInfobox.prototype.defaults = {
     annotation_type: "chap",
-    readonly: true,
+    editable_segments: false,
     empty_message: false,
-    pause_on_segment_end: false,
-    // How long in milliseconds after segment's end can the player pause (less than 500 is unreliable)
-    pause_latency: 500 
+    project_id: false,
+    api_serializer: "ldt_annotate",
+    api_method: "PUT",
+    api_endpoint_template: ""
 };
 
 IriSP.Widgets.CurrentSegmentInfobox.prototype.template = 
-    "<div class='Ldt-CurrentSegmentInfobox'>" 
-    + "    <div class='Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Title'>{{title}}</div>" 
-    + "    <div class='Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Description'>{{description}}</div>" 
-    + "    <div class='Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags'>"
-    + '        {{#tags.length}}'
-    + '        <ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">'
-    + '        {{#tags}}'
-    + '            {{#.}}'
-    + '            <li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
-    + '                <span>{{.}}</span>'
-    + '            </li>'
-    + '            {{/.}}'
-    + '        {{/tags}}'
-    + '        </ul>'
-    + '        {{/tags.length}}'
-    + "    </div>" 
-    + "</div>"
+      '<div class="Ldt-CurrentSegmentInfobox">'
+    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Title">{{title}}</div>'
+    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Description">{{description}}</div>' 
+    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">'
+    +         '{{#tags.length}}'
+    +         '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">'
+    +         '{{#tags}}'
+    +             '{{#.}}'
+    +             '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
+    +                 '<span>{{.}}</span>'
+    +             '</li>'
+    +             '{{/.}}'
+    +         '{{/tags}}'
+    +         '</ul>'
+    +         '{{/tags.length}}'
+    +     '</div>'
+    + '</div>'
 
+IriSP.Widgets.CurrentSegmentInfobox.prototype.editTemplate = 
+      '<div class="Ldt-CurrentSegmentInfobox">'
+    +     '<input type="text" class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-TitleInput Ldt-CurrentSegmentInfobox-Title" value="{{title}}"></input>'   
+    +     '<div class="Ldt-CurrentSegmentInfobox-CancelButton">{{cancel}}</div>'
+    +     '<div class="Ldt-CurrentSegmentInfobox-SubmitButton">{{submit}}</div>'
+    +     '<textarea class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-DescriptionInput Ldt-CurrentSegmentInfobox-Description">{{description}}</textarea>'
+    +     '<div class="Ldt-CurrentSegmentInfobox-Element Ldt-CurrentSegmentInfobox-Tags">'       
+    +         '<div class="Ldt-CurrentSegmentInfobox-CreateTagButton">{{new_tag}}</div>'
+    +         '{{#tags.length}}'
+    +         '<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul">'
+    +         '{{#tags}}'
+    +             '{{#.}}'
+    +             '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
+    +                 '<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value="{{.}}"></input>'
+    +                 '<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">{{delete_tag}}</div>'
+    +             '</li>'
+    +             '{{/.}}'
+    +         '{{/tags}}'
+    +         '</ul>'
+    +         '{{/tags.length}}'
+    +     '</div>'
+    + '</div>'
+    
 IriSP.Widgets.CurrentSegmentInfobox.prototype.messages = {
     fr : {
+        submit : "Soumettre",
+        cancel : "Annuler",
+        new_tag : "Nouveau tag",
+        delete_tag : "Supprimer",
         empty : "Le player vidéo ne lit actuellement aucun segment"
     },
     en: {
-        empty: "The player currently doesn't read any segment"
+        submit : "Submit",
+        cancel : "Cancel",
+        new_tag : "New tag",
+        delete_tag : "Delete tag",
+        empty : "The player currently doesn't read any segment"
     }
 }    
     
 IriSP.Widgets.CurrentSegmentInfobox.prototype.draw = function() {
     var _this = this;
     this.segments = this.getWidgetAnnotations();
-    
+    console.log(this.l10n.submit)
     this.renderTemplate();
     this.currentSegment = false;
-    this.nextPauseOn = -1;
     this.clearBox();
     this.refresh();
     this.onMediaEvent("timeupdate", "refresh");
@@ -57,8 +88,8 @@
         var _segmentBegin = _timeRange[0],
             _segmentEnd = _timeRange[1],
             _list = _this.segments.filter(function(_segment){
-            return _segment.begin == _segmentBegin && _segment.end == _segmentEnd
-        });
+                return _segment.begin.milliseconds == _segmentBegin.milliseconds && _segment.end.milliseconds == _segmentEnd.milliseconds
+            });
         if (_list.length >0){
             if (_this.currentSegment.id != _list[0].id){
                 _this.currentSegment = _list[0];
@@ -68,9 +99,144 @@
                     tags : _this.currentSegment.getTagTexts()
                 }
                 _this.$.html(Mustache.to_html(_this.template, _data))
+                if(_this.editable_segments&&_this.currentSegment){
+                    _this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));            
+                }
             }
         }
     });
+    
+    if(this.editable_segments&&this.currentSegment){
+        this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));        
+    }
+}
+
+IriSP.Widgets.CurrentSegmentInfobox.prototype.enableEditMode = function() {
+    if(this.currentSegment){
+        _data = {
+            title: this.currentSegment.title,
+            description : this.currentSegment.description,
+            tags : this.currentSegment.getTagTexts(),
+            submit : this.l10n.submit,
+            cancel : this.l10n.cancel,
+            new_tag : this.l10n.new_tag,
+            delete_tag : this.l10n.delete_tag
+        }
+        this.$.html(Mustache.to_html(this.editTemplate, _data));
+        this.$.find(".Ldt-CurrentSegmentInfobox-CancelButton").click(this.functionWrapper("disableEditMode"));
+        this.$.find(".Ldt-CurrentSegmentInfobox-CreateTagButton").click(this.functionWrapper("insertTagInput"));
+        this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput"));
+        this.$.find(".Ldt-CurrentSegmentInfobox-SubmitButton").click(this.functionWrapper("onSubmit"))
+    }
+}
+
+IriSP.Widgets.CurrentSegmentInfobox.prototype.disableEditMode = function() {
+    if(this.currentSegment){
+        data = {
+            title: this.currentSegment.title,
+            description : this.currentSegment.description,
+            tags : this.currentSegment.getTagTexts()
+        }
+        this.$.html(Mustache.to_html(this.template, _data));
+        this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode")); 
+    }
+}
+
+IriSP.Widgets.CurrentSegmentInfobox.prototype.insertTagInput = function() {
+    if((!this.currentSegment.getTagTexts().length)&&(!this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").length)){
+        this.$.find(".Ldt-CurrentSegmentInfobox-Tags").prepend('<ul class="Ldt-CurrentSegmentInfobox-Tags-Ul"></ul>')
+    }
+    this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Ul").append(
+        '<li class="Ldt-CurrentSegmentInfobox-Tags-Li">'
+        +'<input type="text" class="Ldt-CurrentSegmentInfobox-Tags-Li-Input" value=""></input>'
+        +'<div class="Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton">'+this.l10n.delete_tag+'</div>'
+        +'</li>');
+    this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-DeleteTagButton").click(this.functionWrapper("deleteTagInput"));
+}
+
+IriSP.Widgets.CurrentSegmentInfobox.prototype.deleteTagInput = function(clickEvent) {
+    $(clickEvent.currentTarget).parent().remove();
+}
+
+IriSP.Widgets.CurrentSegmentInfobox.prototype.onSubmit = function() {
+    new_tags_titles = this.$.find(".Ldt-CurrentSegmentInfobox-Tags-Li-Input").map(function(){
+        if($(this).val()){
+            return $(this).val()
+        }
+    });
+    new_title = this.$.find(".Ldt-CurrentSegmentInfobox-TitleInput").val()
+    new_description = this.$.find(".Ldt-CurrentSegmentInfobox-DescriptionInput").val()
+    
+    var _this = this,
+        _exportedAnnotations = new IriSP.Model.List(this.player.sourceManager), /* Création d'une liste d'annotations contenant une annotation afin de l'envoyer au serveur */
+        _export = this.player.sourceManager.newLocalSource({serializer: IriSP.serializers[this.api_serializer]}),
+        _annotation = new IriSP.Model.Annotation(this.currentSegment.id, _export); /* Création d'une annotation dans cette source avec un ID généré à la volée (param. false) */
+    
+    _annotation.setAnnotationType(this.currentSegment.getAnnotationType().id);
+    _annotation.setMedia(this.currentSegment.getMedia().id);
+    _annotation.setBegin(this.currentSegment.begin);
+    _annotation.setEnd(this.currentSegment.end);
+    _annotation.created = this.currentSegment.created;
+    _annotation.creator = this.currentSegment.creator;
+    _annotation.color = this.currentSegment.color;
+    console.log(this.currentSegment.color)
+    _annotation.title = new_title /* Champ titre */
+    _annotation.description = new_description /* Champ description */
+    var _tagIds = IriSP._(new_tags_titles).map(function(_title) {
+        var _tags = _this.source.getTags(true).searchByTitle(_title, true);
+        if (_tags.length) {
+            var _tag = _tags[0];
+        }
+        else {
+            _tag = new IriSP.Model.Tag(_title.replace(/\W/g,'_'), _this.source);
+            _tag.title = _title;
+            _this.source.getTags().push(_tag);
+        }
+        return _tag.id;
+    });
+    _annotation.setTags(_tagIds);
+    _annotation.project_id = this.project_id;
+    
+    _exportedAnnotations.push(_annotation); /* Ajout de l'annotation à la liste à exporter */
+    _export.addList("annotation",_exportedAnnotations); /* Ajout de la liste à exporter à l'objet Source */    
+    
+    _url = Mustache.to_html(this.api_endpoint_template, {annotation_id: this.currentSegment.id});
+    
+    IriSP.jQuery.ajax({
+        url: _url,
+        type: this.api_method,
+        contentType: 'application/json',
+        data: _export.serialize(), /* L'objet Source est sérialisé */
+        success: function(_data) {
+            console.log("success!")
+            _export.getAnnotations().removeElement(_annotation, true); /* Pour éviter les doublons, on supprime l'annotation qui a été envoyée */
+            _export.deSerialize(_data); /* On désérialise les données reçues pour les réinjecter */
+            _this.source.merge(_export); /* On récupère les données réimportées dans l'espace global des données */
+            _this.segments.forEach(function(_segment){
+                if (_segment.id == _annotation.id){
+                    _this.segments.removeElement(_segment)
+                }
+            })
+            _this.segments.push(_annotation)
+            _this.currentSegment = _annotation
+            _data = {
+                title: _this.currentSegment.title,
+                description : _this.currentSegment.description,
+                tags : _this.currentSegment.getTagTexts()
+            }
+            _this.$.html(Mustache.to_html(_this.template, _data))
+            if(_this.editable_segments&&_this.currentSegment){
+                _this.$.find(".Ldt-CurrentSegmentInfobox").click(_this.functionWrapper("enableEditMode"));             
+            }
+            _this.player.trigger("AnnotationsList.refresh"); /* On force le rafraîchissement du widget AnnotationsList */
+        },
+        error: function(_xhr, _error, _thrown) {
+            console.log("error?"+_error+" "+_thrown)
+            console.log(_xhr)
+            IriSP.log("Error when sending annotation", _thrown);
+            _export.getAnnotations().removeElement(_annotation, true);
+        }
+    });
 }
 
 IriSP.Widgets.CurrentSegmentInfobox.prototype.refresh = function() {
@@ -89,6 +255,9 @@
                     tags : this.currentSegment.getTagTexts()
                 }
                 this.$.html(Mustache.to_html(this.template, _data))
+                if(this.editable_segments&&this.currentSegment){
+                    this.$.find(".Ldt-CurrentSegmentInfobox").click(this.functionWrapper("enableEditMode"));             
+                }
             }
         }
         else {