Added validation before publication
authorveltr
Tue, 06 Nov 2012 18:48:59 +0100
changeset 39 d3d8a88878ed
parent 37 2cae82a5bdc2
child 40 76efa2333f31
Added validation before publication
integration/css/common.css
integration/css/edition.css
integration/edition.html
integration/img/helpwarn.png
integration/img/tooltip.png
integration/js/editor.js
--- a/integration/css/common.css	Tue Nov 06 12:22:30 2012 +0100
+++ b/integration/css/common.css	Tue Nov 06 18:48:59 2012 +0100
@@ -553,9 +553,8 @@
 
 .segment-info {
     padding-top: 12px;
+    overflow: hidden;
     position: relative;
-    width: 100%;
-    overflow: hidden;
 }
 
 /* popin - frise-description */
--- a/integration/css/edition.css	Tue Nov 06 12:22:30 2012 +0100
+++ b/integration/css/edition.css	Tue Nov 06 18:48:59 2012 +0100
@@ -130,11 +130,17 @@
 
 /* col-middle - bloc-segmentation - popin.segmentation */
 
+.segmentation {
+    position: relative;
+    overflow: hidden;
+    padding-top: 12px;
+}
+
 .segmentation h2{
 	font-size: 14px;
 	font-weight: 600;
 	color:#de2500;
-	margin-bottom: 10px;
+	margin: 5px 0 10px;
 }
 
 .time-tangle {
@@ -429,11 +435,8 @@
 .publier-button:hover{
     background-position: 0 -67px;
 }
-.publier-button.disable{
-    background: url(../img/publier-button-sprite.png) 0 -67px no-repeat;
-}
-.publier-button.disable:hover{
-    background-color: none;
+.publier-button.disable, .publier-button.disable:hover{
+    background-position: 0 -134px;
 }
 
 /* Slice Widget */
@@ -470,3 +473,66 @@
 .Ldt-Slice .ui-slider-range {
     background: url(../img/pinstripe-purple.png);
 }
+
+/* Validate */
+
+.validate {
+    float: right; width: 20px; height: 20px; cursor: pointer; background: url(../img/helpwarn.png);
+    position: relative;
+}
+
+.validate:hover {
+    background-position: -20px 0;
+}
+
+.validate.warning {
+    background-position: 0 -20px;
+}
+
+.validate.warning:hover {
+    background-position: -20px -20px;
+}
+
+.validate.critical {
+    background-position: 0 -40px;
+}
+
+.validate.critical:hover {
+    background-position: -20px -40px;
+}
+
+.item-video .validate {
+    margin-right: -5px;
+}
+
+.liste-segment .validate {
+    margin: 6px -1px 0 2px;
+}
+
+.validate-tooltip {
+    position: absolute; top: 16px; left: -225px; width: 235px; padding: 16px 8px 0;
+    background: url(../img/tooltip.png) top no-repeat; z-index: 6; min-height: 30px;
+    color: #FFFFFF; display: none; cursor: auto;
+}
+
+.validate-tooltip ul {
+    padding-left: 14px; list-style: disc; font-size: 12px;
+}
+
+.validate-tooltip li {
+    margin: 2px 0;
+}
+
+.validate:hover .validate-tooltip {
+    display: block;
+}
+
+.validate:hover .validate-tooltip:hover {
+    display: none;
+}
+
+.validate-tooltip:after {
+    bottom: -10px; content: ""; height: 10px;
+    left: 0; position: absolute; width: 100%;
+    background: url(../img/tooltip.png) bottom no-repeat;
+}
--- a/integration/edition.html	Tue Nov 06 12:22:30 2012 +0100
+++ b/integration/edition.html	Tue Nov 06 18:48:59 2012 +0100
@@ -148,7 +148,7 @@
                             </ol>
                         </div>
                         <div class="video-wait"></div>
-                        <a class="publier-button" title="Publier" href="#"></a>
+                        <a class="publier-button disable" title="Publier" href="#"></a>
                     </div>
 
                     <div class="widget">
@@ -187,11 +187,14 @@
 
                     <div class="bloc-segmentation">
                         <div class="Ldt-Slice"></div>
-                        <div class="segment-info segmentation">
+                        <div class="segmentation">
                             <div class="pointer-padder">
                                 <img class="pointer" src="img/popin-triangle.png" alt="" />
                             </div>
                             <div class="popin-content">
+                                <div class="validate">
+                                    <div class="validate-tooltip"></div>
+                                </div>
                                 <h2>
                                     <span class="create-or-edit">Créer un nouveau segment</span>
                                     de
@@ -279,6 +282,9 @@
 
                 <div class="col-right">
                     <div class="liste-segment">
+                        <div class="validate critical">
+                            <div class="validate-tooltip"></div>
+                        </div>
                         <h2>Liste des segments</h2>
                         <div class="frise">
 							<p class="aucun-segment">Aucun segment</p>
Binary file integration/img/helpwarn.png has changed
Binary file integration/img/tooltip.png has changed
--- a/integration/js/editor.js	Tue Nov 06 12:22:30 2012 +0100
+++ b/integration/js/editor.js	Tue Nov 06 18:48:59 2012 +0100
@@ -1,10 +1,16 @@
 
 IriSP.hc_messages = {
-    duration_ : "Durée :",
+    Duration_ : "Durée :",
+    duration_ : "durée :",
     edit_segment: "Éditer le segment",
     segment_down: "Descendre le segment",
     segment_up: "Remonter le segment",
-    delete_segment: "Supprimer le segment"
+    delete_segment: "Supprimer le segment",
+    clone_segment: "Cloner le segment",
+    From_: "De :",
+    to_: "à :",
+    segment_title_placeholder: "Segment sans titre",
+    mashup_title_placeholder: "Hashcut sans titre"
 }
 
 IriSP.Hashcut = function(options) {
@@ -20,10 +26,10 @@
         mashup = new IriSP.Model.Mashup(false, project),
         mediatemplate = _.template('<li class="item-video" data-media-id="<%= id %>"><img src="<%= thumbnail %>" alt="<%= title %>" />'
             + '<span class="video-info"><span class="title-video"><%= title %></span><span class="author"><%= description %></span>'
-            + '<span class="time-length"><%= IriSP.hc_messages.duration_ %> <span><%= duration.toString() %></span></span></span></li>'),
+            + '<span class="time-length"><%= IriSP.hc_messages.Duration_ %> <span><%= duration.toString() %></span></span></span></li>'),
         segmenttemplate = _.template('<li class="item-video" data-segment-id="<%= annotation.id %>" data-media-id="<%= annotation.getMedia().id %>">'
             + '<img src="<%= annotation.getMedia().thumbnail %>" alt="<%= annotation.getMedia().title %>" />'
-            + '<span class="video-info"><span class="title-video"><%= annotation.getMedia().title %></span>'
+            + '<div class="validate <%= annotation.status %>"><div class="validate-tooltip"><ul><li><%= annotation.status_messages.join("</li><li>") %></li></ul></div></div><span class="video-info"><span class="title-video"><%= annotation.getMedia().title %></span>'
             + '<span class="subtitle"><%= annotation.title %></span><span class="duration"><%= annotation.begin.toString() %> - <%= annotation.end.toString() %> (<%= annotation.getDuration().toString() %>)</span>'
             + '<ul class="tools"><li><a class="edit" href="#" title="<%= IriSP.hc_messages.edit_segment %>"></a></li><li><a class="bottom" href="#" title="<%= IriSP.hc_messages.segment_down %>"></a></li>'
             + '<li><a class="top" href="#" title="<%= IriSP.hc_messages.segment_up %>"></a></li><li><a class="delete" href="#" title="<%= IriSP.hc_messages.delete_segment %>"></a></li></ul></span></li>'),
@@ -33,9 +39,58 @@
             + '<div class="media-section media-segment-section" style="left:<%= left %>px; width:<%= width %>px; background:<%= annotation.getMedia().color %>"></div>'
             + '<div class="media-section media-current-section" style="left:<%= currentleft %>px; width:<%= currentwidth %>px;"><div class="media-current-section-inner"></div></div>'
             + '<div class="popin media-segment-popin" style="left:<%= popleft %>px"><img style="left:<%= pointerpos %>px;" class="pointer" src="img/popin-triangle.png" alt="" /><div class="popin-content">'
-            + '<h3><%= annotation.title %></h3><a href="#" class="button reprendre-segment" data-segment-id="<%= annotation.id %>">Cloner le segment</a>'
-            + '<p>De: <span><%= annotation.begin.toString() %></span> à <span><%= annotation.end.toString() %></span> (durée: <span><%= annotation.getDuration().toString() %></span>)</p>'
+            + '<h3><%= annotation.title %></h3><a href="#" class="button reprendre-segment" data-segment-id="<%= annotation.id %>"><%= IriSP.hc_messages.clone_segment %></a>'
+            + '<p><%= IriSP.hc_messages.From_ %> <span><%= annotation.begin.toString() %></span> <%= IriSP.hc_messages.to_ %> <span><%= annotation.end.toString() %></span> (<%= IriSP.hc_messages.duration_ %> <span><%= annotation.getDuration().toString() %></span>)</p>'
             + '</div></div></div></div>');
+    
+    /* Validation of segments and mashup */
+    
+    var segmentcritical = [
+        {
+            validate: function(_s) {
+                var _d = _s.getDuration();
+                return (_d > 1000 && _d < 180000);
+            },
+            message: "La durée du segment doit être comprise entre 1 seconde et trois minutes"
+        },
+        {
+            validate: function(_s) {
+                return (!!_s.title && _s.title !== IriSP.hc_messages.segment_title_placeholder);
+            },
+            message: "Un titre doit être donné au segment"
+        }
+    ];
+    var segmentwarning = [
+        {
+            validate: function(_s) {
+                return (_s.description);
+            },
+            message: "Il est recommandé de donner une description au segment"
+        }
+    ];
+    
+    var mashupcritical = [
+        {
+            validate: function(_m) {
+                return _m.segments.length > 2;
+            },
+            message: "Un hashcut doit être composé d'au moins trois segments"
+        },
+        {
+            validate: function(_m) {
+                return (!!_m.title && _m.title !== IriSP.hc_messages.mashup_title_placeholder);
+            },
+            message: "Un titre doit être donné au hashcut"
+        }
+    ];
+    var mashupwarning = [
+        {
+            validate: function(_m) {
+                return !!_m.description
+            },
+            message: "Il est recommandé de donner une description au hashcut"
+        }
+    ];
 
     /* Fill left column with Media List */
 
@@ -84,6 +139,7 @@
     
     function updateMashupUI() {
         var listhtml = '', vizhtml = '', t = 0, k = mashup.duration ? (100 / mashup.duration) : 0;
+        var critical = false, warning = false, messages = [];
         mashup.segments.forEach(function(_s) {
             listhtml += segmenttemplate(_s);
             var vizdata = {
@@ -93,8 +149,35 @@
                 segmentid: _s.annotation.id
             }
             vizhtml += viztemplate(vizdata);
+            if (_s.annotation.status === "critical") {
+                critical = true;
+            }
             t += _s.duration.milliseconds;
         });
+        if (critical) {
+            messages.push("Certains segments ne sont pas valides");
+        }
+        
+        _(mashupcritical).each(function(sc) {
+            if (!sc.validate(mashup)) {
+                critical = true;
+                messages.push(sc.message);
+            }
+        });
+        _(mashupwarning).each(function(sc) {
+            if (!sc.validate(mashup)) {
+                warning = true;
+                messages.push(sc.message);
+            }
+        });
+        mashup.status = critical ? "critical" : (warning ? "warning" : "valid");
+        if (!messages.length) {
+            messages.push("Le hashcut est valide !");
+        }
+        $(".publier-button").toggleClass("disable", critical);
+        
+        $(".liste-segment .validate").removeClass("critical warning valid").addClass(mashup.status);
+        $(".liste-segment .validate-tooltip").html("<ul><li>" + messages.join("</li><li>")+"</li></ul>");
         
         var intervals = [ 1000, 2000, 5000, 10000, 30000, 60000, 120000, 300000, 600000, 900000, 1800000, 3600000, 7200000 ];
         
@@ -435,7 +518,7 @@
    
     var currentMedia, currentSegment;
     
-    function updateSliderAndTangles() {
+    function updateSegmentUI() {
         if (currentMedia && currentSegment) {
             var start = currentSegment.begin,
                 end = currentSegment.end,
@@ -450,11 +533,34 @@
             tangleStart.text(start.toString(tangleStart.hasClass("active"))).attr("data-milliseconds",start.milliseconds);
             tangleEnd.text(end.toString(tangleEnd.hasClass("active"))).attr("data-milliseconds",end.milliseconds);
             tangleDuration.text(dur.toString(tangleDuration.hasClass("active"))).attr("data-milliseconds",dur.milliseconds);
-            $(".segment-info .pointer").css("left", p + "%");
+            $(".segmentation .pointer").css("left", p + "%");
             $(".media-current-section").css({
                 left: (k * start) + "%",
                 width: (k * dur) + "%"
-            })
+            });
+            var messages = [],
+                critical = false,
+                warning = false;
+            _(segmentcritical).each(function(sc) {
+                if (!sc.validate(currentSegment)) {
+                    critical = true;
+                    messages.push(sc.message);
+                }
+            });
+            _(segmentwarning).each(function(sc) {
+                if (!sc.validate(currentSegment)) {
+                    warning = true;
+                    messages.push(sc.message);
+                }
+            });
+            currentSegment.status = critical ? "critical" : (warning ? "warning" : "valid");
+            if (!messages.length) {
+                messages.push("Le segment est valide !")
+            }
+            currentSegment.status_messages = messages;
+            
+            $(".segmentation .validate").removeClass("critical warning valid").addClass(currentSegment.status);
+            $(".segmentation .validate-tooltip").html("<ul><li>" + currentSegment.status_messages.join("</li><li>")+"</li></ul>");
         }
     }
     
@@ -484,18 +590,18 @@
                 currentSegment.setMedia(currentMedia.id);
                 currentSegment.setBegin(0);
                 currentSegment.setEnd(currentMedia.duration);
-                currentSegment.title = "Segment sans titre";
-                currentSegment.description = "Extrait de « " + currentMedia.title + " »";
+                currentSegment.title = IriSP.hc_messages.segment_title_placeholder;
+                currentSegment.description = "";
                 currentSegment.on("change-begin", function() {
                     if (currentMedia && currentSegment === this) {
                         currentMedia.setCurrentTime(this.begin);
-                        updateSliderAndTangles();
+                        updateSegmentUI();
                     }
                 });
                 currentSegment.on("change-end", function() {
                     if (currentMedia && currentSegment === this) {
                         currentMedia.setCurrentTime(this.end);
-                        updateSliderAndTangles();
+                        updateSegmentUI();
                     }
                 });
                 currentSegment.on("enter", function() {
@@ -515,7 +621,7 @@
             }
             $(".add-segment").val(addMode ? "Ajouter au Hashcut" : "Sauvegarder");
             $(".create-or-edit").text(addMode ? "Créer un nouveau segment" : "Modifier le segment");
-            updateSliderAndTangles();
+            updateSegmentUI();
             media.show();
             $("#segment-title").val(currentSegment.title);
             $("#segment-description").val(currentSegment.description);
@@ -800,12 +906,14 @@
     $("#segment-title").on("keyup change input paste", function() {
         if (currentMedia && currentSegment) {
             currentSegment.title = $(this).val();
+            updateSegmentUI();
             updateMashupUI();
         }
     });
     $("#segment-description").on("keyup change input paste", function() {
         if (currentMedia && currentSegment) {
             currentSegment.description = $(this).val();
+            updateSegmentUI();
         }
     });
     $("#segment-form").submit(function() {
@@ -1021,10 +1129,21 @@
     });
     
     /* Changing Hashcut Title and description */
-   
+    
+    mashup.title = IriSP.hc_messages.mashup_title_placeholder;
+    $(".title-video-wrap a").text(mashup.title);
+    $("#hashcut-title").val(mashup.title);
+    
     $("#hashcut-title").on("keyup change input paste", function() {
         mashup.title = $(this).val();
         $(".title-video-wrap a").text(mashup.title);
+        updateMashupUI();
     });
     
+    $("#hashcut-description").on("keyup change input paste", function() {
+        mashup.description = $(this).val();
+        updateMashupUI();
+    });
+    
+    updateMashupUI();
 }