design work on templates, redirect to home on /, implemented accept and reject revisions shortcuts when applicable
authordurandn
Thu, 07 Jul 2016 16:34:31 +0200
changeset 62 8702ab13783e
parent 61 22c88b2c325f
child 63 96e35b9957ba
design work on templates, redirect to home on /, implemented accept and reject revisions shortcuts when applicable
src/iconolab/auth/views.py
src/iconolab/models.py
src/iconolab/settings/__init__.py
src/iconolab/static/iconolab/css/iconolab.css
src/iconolab/templates/iconolab/change_annotation.html
src/iconolab/templates/iconolab/detail_annotation.html
src/iconolab/templates/iconolab/detail_revision.html
src/iconolab/templates/iconolab/home.html
src/iconolab/templates/iconolab_base.html
src/iconolab/templates/partials/image_annotations_list.html
src/iconolab/urls.py
src/iconolab/views.py
--- a/src/iconolab/auth/views.py	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/auth/views.py	Thu Jul 07 16:34:31 2016 +0200
@@ -37,7 +37,6 @@
 		return super(LoginView, self).get(request, *args, **kwargs)
 	
 	def form_valid(self, form):
-		print(self.request.POST)
 		login(self.request, form.get_user())
 		return HttpResponseRedirect(self.get_success_url())
 	
--- a/src/iconolab/models.py	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/models.py	Thu Jul 07 16:34:31 2016 +0200
@@ -119,8 +119,12 @@
     tag_count = models.IntegerField(blank=True, null=True, default=0)
     
     def contributors(self):
-        # returns users that submitted an accepted revision
-        return
+        contributors = []
+        for revision in self.annotation.revisions.filter(state__in=[AnnotationRevision.ACCEPTED, AnnotationRevision.STUDIED]):
+            if revision.author not in contributors:
+                contributors.append(revision.author)
+        print(contributors)
+        return contributors
 
 
 class Annotation(models.Model):
@@ -164,18 +168,27 @@
     # Call when we're validating an awaiting revision whose parent is the current revision AS IT WAS CREATED
     @transaction.atomic
     def validate_existing_revision(self, revision_to_validate):
-        if revision_to_validate.parent_revision == current_revision:
+        if revision_to_validate.parent_revision == self.current_revision and revision_to_validate.state == AnnotationRevision.AWAITING:
             self.current_revision = revision_to_validate
             revision_to_validate.state = AnnotationRevision.ACCEPTED
             revision_to_validate.save()
             self.save()
-            
+    
+    # Call to reject a 
+    @transaction.atomic
+    def reject_existing_revision(self, revision_to_reject):
+        if revision_to_reject.state == AnnotationRevision.AWAITING:
+            revision_to_reject.state = AnnotationRevision.REJECTED
+            revision_to_reject.save()
+        
     # Call when we're validating an awaiting revision whose parent isn't the current revision OR IF IT WAS CHANGED BY THE ANNOTATION AUTHOR
     @transaction.atomic
     def merge_existing_revision(self, title, description, fragment, tags, revision_to_merge):
         merged_revision = self.make_new_revision(author=self.author, title=title, description=description, fragment=fragment, tags=tags)
         merged_revision.merge_parent_revision = revision_to_merge
         merged_revision.save()
+        revision_to_merge.state = AnnotationRevision.STUDIED
+        revision_to_merge.save()
         self.current_revision=merged_revision
         self.save()
 
@@ -185,11 +198,13 @@
     AWAITING = 0
     ACCEPTED = 1
     REJECTED = 2
+    STUDIED = 3
     
     REVISION_STATES = (
         (AWAITING, 'awaiting'),
         (ACCEPTED, 'accepted'),
-        (REJECTED, 'rejected')
+        (REJECTED, 'rejected'),
+        (STUDIED, 'studied'),
     )
     
     revision_guid = models.UUIDField(default=uuid.uuid4)
--- a/src/iconolab/settings/__init__.py	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/settings/__init__.py	Thu Jul 07 16:34:31 2016 +0200
@@ -94,6 +94,7 @@
                 'django.contrib.messages.context_processors.messages',
                 'django.core.context_processors.media',
                 'django.core.context_processors.static',
+                'django.core.context_processors.i18n',
                 'iconolab.utils.context_processors.notifications',
             ],
         },
@@ -136,8 +137,6 @@
 # Internationalization
 # https://docs.djangoproject.com/en/1.9/topics/i18n/
 
-LANGUAGE_CODE = 'en-us'
-
 TIME_ZONE = 'UTC'
 
 USE_I18N = True
--- a/src/iconolab/static/iconolab/css/iconolab.css	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/static/iconolab/css/iconolab.css	Thu Jul 07 16:34:31 2016 +0200
@@ -6,3 +6,47 @@
 
 .form-drawing-wrapper .selected {border: 1px solid orange; color: white; background-color: orange}
 .showPointer {cursor: pointer;}
+
+.annotation-content{
+	margin-top: 15px;
+	margin-bottom: 15px;
+}
+
+.collection-home-btn{
+	margin-top: 5px;
+}
+
+.revision-link:hover{
+  	text-decoration: underline;
+}
+
+.item-image-thumbnail:hover{
+	cursor: pointer;
+}
+
+ul.annotation-comments{
+	background-color: #ededed;
+}
+li.list-group-item{
+	border: 1px solid #bbb
+}
+
+.comment-reply-link{
+	cursor: pointer;
+}
+.comment-subtext{
+	font-size:0.9em; 
+	display:inline;
+}
+.comment-metacategories{
+	font-size:0.9em; 
+	display:inline;
+}
+.comment-separator{
+	margin-top: 10px;
+	margin-bottom: 5px;
+}
+
+.pagination-shortcut{
+	cursor: pointer;	
+}
\ No newline at end of file
--- a/src/iconolab/templates/iconolab/change_annotation.html	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/templates/iconolab/change_annotation.html	Thu Jul 07 16:34:31 2016 +0200
@@ -31,7 +31,7 @@
 			
 			<div class="col-md-8">
 				<div ref="image" id="iconolab-image-wrapper">
-					{% thumbnail image.media "x800" crop="center" as im %}
+					{% thumbnail image.media "835x835" crop=False as im %}
 						<svg class="cut-canvas">
 							<image class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
 	    					<path class="image-path" d="{% if annotation %}{{ annotation.current_revision.fragment }}{% endif %}"></path>
@@ -50,12 +50,9 @@
 			
 			<div class="col-md-6">
 				<div class="small-image-wrapper" style="position: relative">
-					{% thumbnail image.media "x300" crop="center" as im %}
-
-						<svg ref="smallSvgWrapper" width="{{ im.width }}" height="{{ im.height }}" version="1.1">
-							
+					{% thumbnail image.media "500x360" crop=False as im %}
+						<svg ref="smallSvgWrapper" width="{{ im.width }}" height="{{ im.height }}" version="1.1">			
 							<image ref="smallImage" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0"  width="{{ im.width }}" height="{{ im.height }}"></image>
-
 							<defs>
 								<mask id="smallImage">
 									<rect x="0" y="0" width="{{ im.width }}" height="{{ im.height }}" fill="white"/>
@@ -149,9 +146,10 @@
                         id="id_{{ form.comment.name }}" ></textarea>
                     </fieldset>
         			<input v-model="normalizePath" type="hidden" name="fragment"></input>
-        			<button type="submit" class="save btn btn-default">Enregister</button>
-                    <a class="btn btn-default" href="{% if annotation %}{% url 'annotation_detail' collection_name image_guid annotation_guid %}{% else %}{% url 'image_detail' collection_name image_guid %}{% endif %}" role="button">Retour</a>
-    			</form>
+        			<button type="submit" class="save btn btn-default btn-sm">Enregister</button>
+                    <a class="btn btn-default btn-sm" href="{% if annotation %}{% url 'annotation_detail' collection_name image_guid annotation_guid %}{% else %}{% url 'item_detail' collection_name image.item.item_guid %}{% endif %}" role="button">Retour</a>
+    			    <br><br>
+                </form>
 			</div>
 			
 		</div>
--- a/src/iconolab/templates/iconolab/detail_annotation.html	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_annotation.html	Thu Jul 07 16:34:31 2016 +0200
@@ -14,7 +14,7 @@
 		<div id="detail-annotation" class="col-md-12">
 			<div v-show="!showZoom" class="col-md-6">
 				<div class="small-image-wrapper" style="position: relative">
-					{% thumbnail annotation.image.media "x300" crop="center" as im %}
+					{% thumbnail annotation.image.media "300x300" crop=False as im %}
 						<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
 
 						<svg width="{{ im.width }}" height="{{ im.height }}" version="1.1" style="position:absolute; top:0px; left: 0px">
@@ -27,24 +27,31 @@
 						
 					{% endthumbnail %}
 				</div>
-        <p @click="toggleZoomView" style="padding-top:2px"><i class="fa fa-search-plus showPointer"></i></p>
+        	<p @click="toggleZoomView" style="padding-top:2px"><i class="fa fa-search-plus showPointer"></i></p>
 			</div>
 
-			<div v-show="!showZoom" class='col-md-6'>
-        <h4>Annotation créée par {{ annotation.author.username }}</h4>
-                
-				<p> <strong>Title:</strong> {{ annotation.current_revision.title }}</p>
-				<p> <strong>Description:</strong> {{ annotation.current_revision.description }}</p>
-        <p><strong>Tags:</strong></p>
-        <typeahead :read-only="1" :tags="{{ tags_data }}"></typeahead>
-				<a href="{% url 'annotation_edit' collection_name image_guid annotation_guid  %}">{% if user == annotation.author %}Editer{% else %}Proposer une révision{% endif %}</a>
-                
-			</div>
+        <div v-show="!showZoom" id="detail-annotation" class='col-xs-6' style="">
+            <h4>Annotation créée par {{ annotation.author.username }}</h4>    
+  		    <p><strong>Titre:</strong> {{ annotation.current_revision.title }}</p>
+  		    <p><strong>Description:</strong> {{ annotation.current_revision.description }}</p>
+            <p><strong>Tags:</strong></p>
+            <typeahead :read-only="1" :tags="{{ tags_data }}"></typeahead>
+            {% if user.is_authenticated %}
+              <br>
+  		      <a href="{% url 'annotation_edit' collection_name image_guid annotation_guid  %}" class="btn btn-default btn-sm">
+                {% if user == annotation.author %}
+                  <span class="glyphicon glyphicon-edit"></span> Editer l'annotation
+                {% else %}
+                  <span class="glyphicon glyphicon-share"></span> Proposer une révision
+                {% endif %}
+              </a>  
+		    {% endif %}
+          </div>
       <!-- zoomView -->
       <div class="col-md-12 zoom-view" style="display:none" v-show="showZoom">
         
         <div class="col-md-2">
-          {% thumbnail annotation.image.media "x100" crop="center" as im %}
+          {% thumbnail annotation.image.media "100x100" crop=False as im %}
           <zoomview ref="zoomview" :zoomtarget="'zoomTarget'" :image-url="'{{ im.url }}'" :width="{{ im.width }}" :height="{{ im.height }}"></zoomview>
           {% endthumbnail %}
 
@@ -52,7 +59,7 @@
         </div>
 
         <div class="col-md-8">
-          {% thumbnail annotation.image.media "x900" crop="center" as im %}
+          {% thumbnail annotation.image.media "900x900" crop=False as im %}
             <svg id="zoomTarget" ref="zoomTarget" width="{{ im.width }}" height="{{ im.height }}">
               <image class="main-image" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="{{ im.url }}" x="0" y="0" width="{{ im.width }}" height="{{ im.height }}"></image>
               <g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
@@ -68,30 +75,103 @@
 
 		</div>
         <div class='col-md-12'>
-          <h4>Commentaires</h4>
-          {% get_comment_list for annotation as comment_list %}
-          <ul class="list-group" id="comments">
-            {% for comment in comment_list %}
-              <li class="list-group-item" id="c{{ comment.id }}">
-                <p><p>
-                <p>{{ comment.comment }} </p>
-                <div style="font-size:0.9em">{{ comment.submit_date }}&nbsp;-&nbsp; <b>{{ comment.name }}</b>
-                {% if comment.allow_thread %}&nbsp;-&nbsp;  <a href="{{ comment.get_reply_url }}">{% trans "Reply" %}</a>{% endif %}</div>
+          <h4 id="annotation-comments-header">Commentaires</h4>
+          <ul class="list-group annotation-comments" id="comments">
+            {% for comment in comments %}
+              <li class="list-group-item" id="c{{ comment.id }}" style="margin-left:calc({{ comment.level }}*5px);">
+                <p id="c{{comment.id}}-content" class="comment-content">{{ comment.comment }}</p>
+                <hr class="comment-separator">
+                {% if comment.allow_thread and user.is_authenticated %}<div class="pull-right"><a class="btn btn-default btn-xs reply-to-btn" id="reply-to-{{comment.id}}" class="comment-reply-link">Répondre</a></div>{% endif %}
+                <div id="c{{comment.id}}-subtext" class="comment-subtext">{{ comment.submit_date|date:"d/m/Y" }} à {{ comment.submit_date|time:"H:i" }}&nbsp;-&nbsp; <b>{{ comment.name }}</b></div>
+                <div id="c{{comment.id}}-label-list" class="comment-metacategories">
+                {% if comment.revision or comment.metacategories.count > 0 %}&nbsp;-&nbsp;{% endif %}
                 {% if comment.revision %}
-                  <a href="{% url 'revision_detail' collection_name image_guid annotation_guid comment.revision.revision_guid %}">
-                    <span class="label {% if comment.revision.author == annotation.author %}label-success{% else %}label-warning{% endif %}">
-                    
-                    {% if comment.revision.author == annotation.author %}Voir révision{% else %}Voir proposition{% endif %}
-                    </span>
+                  <a href="{% url 'revision_detail' collection_name image_guid annotation_guid comment.revision.revision_guid %}">  
+                    <span class="label 
+                    {% if comment.revision.author == annotation.author %}
+                      label-success
+                    {% else %}
+                      {% if comment.revision.state == 0 %}
+                        label-warning
+                      {% elif comment.revision.state == 1 %}
+                        label-success
+                      {% elif comment.revision.state == 2 %}
+                        label-danger
+                      {% elif comment.revision.state == 3 %}
+                        label-primary
+                      {% endif %}
+                    {% endif %} revision-link"> 
+                    {% if comment.revision.author == annotation.author %}
+                      Voir révision
+                    {% else %}
+                      Voir proposition 
+                      {% if comment.revision.state == 0 %}
+                        (en attente)
+                      {% elif comment.revision.state == 1 %}
+                        (validée)
+                      {% elif comment.revision.state == 2 %}
+                        (rejetée)
+                      {% elif comment.revision.state == 3 %}
+                        (étudiée)
+                      {% endif %}
+                    {% endif %}</span> 
                   </a>
                 {% endif %}
                 {% for metacategory in comment.metacategories.all %}
                   <span class="label label-info">{{metacategory.label}}</span>
                 {% endfor %}
-              </li>
+                </div>
+                </li>
             {% endfor %}
           </ul>
-        </div>
+          <ul class="pagination pull-right" style="margin-left: 15px;">
+            <li class="active pagination-label"><a>Commentaires par page: </a></li>
+            <li class="{% if comments.paginator.per_page == 5 %}active{% endif %}">
+              <a {% if comments.paginator.per_page != 5 %}href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page=1&perpage=5"{% endif %}>5</a>
+            </li>
+            <li class="{% if comments.paginator.per_page == 10 %}active{% endif %}">
+              <a {% if comments.paginator.per_page != 10 %}href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page=1&perpage=10"{% endif %}>10</a>
+            </li>
+            <li class="{% if comments.paginator.per_page == 25 %}active{% endif %}">
+              <a {% if comments.paginator.per_page != 25 %}href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page=1&perpage=25"{% endif %}>25</a>
+            </li>
+            <li class="{% if comments.paginator.per_page == 100 %}active{% endif %}">
+              <a {% if comments.paginator.per_page != 100 %}href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page=1&perpage=100"{% endif %}>100</a>
+            </li>
+          </ul>
+          &nbsp;
+          {% if comments.has_previous or comments.has_next %}
+            <ul class="pagination pull-right">
+              {% if comments.has_previous %}
+              <li>
+                <a href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page={{comments.previous_page_number}}&perpage={{comments.paginator.per_page}}" aria-label="Previous">
+                  <span aria-hidden="true">&laquo;</span>
+                </a>
+              </li>
+              {% endif %}
+              
+              {% for page in comments.paginator.page_range %}
+<!--                 {% if not forloop.first %} -->
+<!--                   <li id="shortcut-before-{{page}}" class="pagination-shortcut"><a>...</a></li> -->
+<!--                 {% endif %} -->
+                <li id="page-link-{{page}}" class="pagination-link {% if page == comments.number %}active{% endif %}">
+                  <a {% if page != comments.number %}href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page={{page}}&perpage={{comments.paginator.per_page}}"{% endif %}>{{page}}</a>
+                </li>
+                
+              {% endfor %}
+              
+              {% if comments.has_next %}
+              <li>
+                <a href="{% url 'annotation_detail' collection_name image_guid annotation_guid %}?page={{comments.next_page_number}}&perpage={{comments.paginator.per_page}}" aria-label="Next">
+                  <span aria-hidden="true">&raquo;</span>
+                </a>
+              </li>
+              {% endif %}
+            </ul>
+          {% endif %}
+          </div>
+        
+        
         <div class='col-md-12'>
         {% if user.is_authenticated %}
         {% if not comment_form %}
@@ -103,11 +183,21 @@
           {{ comment_form.object_pk }}
           {{ comment_form.timestamp }}
           {{ comment_form.security_hash }}
-          {{ comment_form.reply_to }}
+          <input id="reply-to-field" type="hidden" name="reply_to" value="0"></input>
           <input type="hidden" name="next" value="{% url 'annotation_detail' collection_name image_guid annotation_guid %}">
           <h4> Commenter en tant que {{user.username}} </h4>
+          <div class="reply-to-container">
+            <label id="form-reply-to-label" class="control-label reply-to-label" for="id_{{ comment_form.comment.name }}">En réponse à: </label>
+            <div class="alert alert-info reply-to-alert">
+               <p class="reply-to-content comment-content"></p>
+               <hr class="comment-separator">
+               <div class="reply-to-subtext comment-subtext"></div>
+               <div class="reply-to-label-list comment-metacategories"></div>
+            </div>
+            <a class="btn btn-default btn-sm reply-to-cancel">Annuler et répondre sur le fil principal</a><br><br>
+          </div>
           <fieldset class="form-group {% if comment_form.comment.errors %}has-error{% endif %}">
-            <label class="control-label" for="id_{{ comment_form.comment.name }}">{{ comment_form.comment.label }}</label>
+            <label class="control-label" for="id_{{ comment_form.comment.name }}">Commentaire</label>
             {% if comment_form.comment.errors %}
               <div class="alert alert-danger" role="alert">
                 <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
@@ -133,7 +223,7 @@
           </p>
         </form>
         {% endif %}
-        <div></div>
+        
 	</div>
 {% endblock %}
 
@@ -166,5 +256,27 @@
         'Zoomview': iconolab.VueComponents.Zoomview
       }
     });
+    
+    $(".reply-to-container").hide()
+    $(".reply-to-btn").click(function(event){
+        $(".reply-to-container").hide()
+        var commentID = /reply\-to\-([0-9]+)/.exec($(this).attr("id"))[1];
+        var comment_content = $("#c"+commentID+"-content").html();
+        var comment_subtext = $("#c"+commentID+"-subtext").html();
+        var comment_labels = $("#c"+commentID+"-label-list").html();
+        $(".reply-to-alert .reply-to-content").html(comment_content);
+        $(".reply-to-alert .reply-to-subtext").html(comment_subtext);
+        $(".reply-to-alert .reply-to-label-list").html(comment_labels);
+        $(".reply-to-container").slideDown();
+        $("#form-reply-to-label").get(0).scrollIntoView();
+        $("#reply-to-field").val(commentID);
+    })
+    $(".reply-to-cancel").click(function(event){
+      $(".reply-to-container").hide()
+      $(".reply-to-alert .reply-to-content").html("");
+      $(".reply-to-alert .reply-to-subtext").html("");
+      $(".reply-to-alert .reply-to-label-list").html("");
+      $("#reply-to-field").val("0");
+    })
   </script>
 {% endblock %}
\ No newline at end of file
--- a/src/iconolab/templates/iconolab/detail_revision.html	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_revision.html	Thu Jul 07 16:34:31 2016 +0200
@@ -8,25 +8,26 @@
 {% load iconolab_tags %}
 
 {% block content %}
-	<a href="{% url 'image_detail' collection_name image_guid %}"><i class="fa fa-list"></i> Revoir l'image </a>
 	<div id="annotation-wrapper" class="row" style="border: 1px solid gray">
-		
-		<div v-show="formView" class="col-md-12">
+		{% if not user.is_authenticated and revision.state != 1 %}
+            <p>Connectez vous pour voir cette proposition de révision.</p>
+        {% else %}
+		<div v-show="formView" class="col-md-12 annotation-content">
 			<div class="col-xs-6">
 				<div class="small-image-wrapper" style="position: relative">
 					{% thumbnail image.media "x300" crop="center" as im %}
 						<img v-el:small-image src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
-
 						<svg width="{{ im.width }}" height="{{ im.height }}" version="1.1" style="position:absolute; top:0px; left: 0px">
-
 							<g transform="matrix({% transform_matrix im_width=im.width im_height=im.height max_x=100 max_y=100 %})">
 								<path d="{{ revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
 							</g>
-
 						</svg>
-						
 					{% endthumbnail %}
 				</div>
+                <br>
+                <a href="{% url 'image_detail' collection_name image_guid %}"><i class="fa fa-picture-o" aria-hidden="true"></i> Revoir l'image </a><br>
+                <a href="{% url 'annotation_detail' collection_name image_guid annotation_guid  %}"><i class="fa fa-reply" aria-hidden="true"></i> Retour sur l'annotation</a><br>
+                {% if revision.parent_revision %}<a href="{% url 'revision_detail' collection_name image_guid annotation_guid revision.parent_revision.revision_guid %}"><i class="fa fa-history" aria-hidden="true"></i> Voir révision précédente</a><br>{% endif %}
 			</div>
 			<div id="revision-detail" class='col-xs-6' style="">
                 <h4>Annotation révisée par {{ revision.author.username}} </h4>
@@ -34,16 +35,39 @@
 				<p> <strong>Description:</strong> {{ revision.description }}</p>
 				<p><strong>Tags:</strong></p>
                 <typeahead :read-only="1" :tags="{{ tags_data }}"></typeahead>
+                <br>
                 <div class="alert alert-info" role="alert">
-                  <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
+                  <span class="glyphicon glyphicon-comment" aria-hidden="true"></span>
                   <span class="sr-only">Info:</span>
-                    <b>Revision created by {{ revision.author }} on the {{ revision.created }}</b><br>
-                    "{{ revision.creation_comment.first.comment }}"
+                    <b>Révision par {{ revision.author }} le {{ revision.created }}</b><br>
+                    <i class="fa fa-quote-left" aria-hidden="true"></i> {{ revision.creation_comment.first.comment }} <i class="fa fa-quote-right" aria-hidden="true"></i>
                 </div>
-				<a href="{% url 'annotation_detail' collection_name image_guid annotation_guid  %}">Retour sur l'annotation</a>
-				{% if revision.parent_revision %} | <a href="{% url 'revision_detail' collection_name image_guid annotation_guid revision.parent_revision.revision_guid %}">Voir révision précédente</a>{% endif %}
-			</div>
+                  {% if revision.state == 0 and user == annotation.author %}
+                  <br>
+                  <div class="btn-group" role="group">
+                    {% if revision.parent_revision == annotation.current_revision %}
+                      <button id="accept-revision" type="button" class="btn btn-default"><span class="glyphicon glyphicon-ok"></span> Accepter cette révision</button>
+                    {% endif %}
+                    <button id="merge-revision" type="button" class="btn btn-default"><span class="glyphicon glyphicon-eye-open"></span> Etudier cette révision</button>
+                    <button id="reject-revision" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Rejeter cette révision</button>
+                  </div><br><br>
+                  
+                  {% if revision.parent_revision == annotation.current_revision %}
+                    <div id="accept-info" class="alert alert-warning alert-merge"> Si vous acceptez cette proposition, elle deviendra automatiquement la version courante de l'annotation.<br><br>
+                       <a class="btn btn-default" href="{% url 'annotation_merge' collection_name image_guid annotation_guid revision_guid %}?auto_accept=True"> Valider </a>
+                    </div>
+                  {% endif %}
+                  <div id="reject-info" class="alert alert-warning alert-merge"> Attention: l'action de rejeter une proposition est irréversible.<br><br>
+                     <a class="btn btn-default" href="{% url 'annotation_merge' collection_name image_guid annotation_guid revision_guid %}?auto_reject=True"> Valider </a>
+                  </div>
+                  <div id="merge-info" class="alert alert-warning alert-merge"> En étudiant la révision, vous accédez à une interface qui vous permet notamment de comparer la proposition avec la version courante de l'annotation avant d'en accepter tout ou partie. <br><br>
+                     <a class="btn btn-default" href="{% url 'annotation_merge' collection_name image_guid annotation_guid revision_guid %}"> Valider </a>
+                  </div>
+                {% endif %}
+               
+          </div>
 		</div>
+        {% endif %}
 {% endblock %}
 
 {% block footer_js %}
@@ -53,5 +77,24 @@
       components: {'Typeahead': iconolab.VueComponents.Typeahead }, 
       methods: { yo: function(){alert(1);} }
     });
+    $(".alert-merge").hide();
+    $("#accept-revision").click(function(){
+        if($("#accept-info").is(":hidden")){
+            $(".alert-merge").hide();
+            $("#accept-info").slideDown();
+        }
+    });
+    $("#merge-revision").click(function(){
+        if($("#merge-info").is(":hidden")){
+            $(".alert-merge").hide();
+            $("#merge-info").slideDown();
+        }
+    });
+    $("#reject-revision").click(function(){
+        if($("#reject-info").is(":hidden")){
+            $(".alert-merge").hide();
+            $("#reject-info").slideDown();
+        }
+    })
   </script>
 {% endblock %}
--- a/src/iconolab/templates/iconolab/home.html	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/templates/iconolab/home.html	Thu Jul 07 16:34:31 2016 +0200
@@ -1,11 +1,15 @@
 {% extends 'iconolab_base.html' %}
 
+{% load i18n %}
 {% load staticfiles %}
-
 {% load thumbnail %}
-
 {% load iconolab_tags %}
 
 {% block content %}
 <h1>Fond Ingres <a href="{% url 'collection_home' 'ingres' %}"><span class="glyphicon glyphicon-link" aria-hidden="true"></span></a></h1>
+
+{% get_current_language as LANGUAGE_CODE %}
+{% get_available_languages as LANGUAGES %}
+{% get_current_language_bidi as LANGUAGE_BIDI %}
+the current language is {{ LANGUAGE_CODE }}
 {% endblock %}
\ No newline at end of file
--- a/src/iconolab/templates/iconolab_base.html	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/templates/iconolab_base.html	Thu Jul 07 16:34:31 2016 +0200
@@ -9,6 +9,7 @@
 		{% block main_js %}
 			<!--<script src="{% static 'iconolab/js/dist/bundle.js' %}" type="text/javascript"></script>-->
 			<script src="{% static 'iconolab/js/iconolab-bundle/dist/build.js' %}" type="text/javascript"></script>
+            <script src="{% static 'iconolab/js/iconolab-bundle/node_modules/jquery/dist/jquery.min.js' %}" type="text/javascript"></script>
 		{% endblock %}
 		{% block page_js %} {% endblock %}
 
--- a/src/iconolab/templates/partials/image_annotations_list.html	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/templates/partials/image_annotations_list.html	Thu Jul 07 16:34:31 2016 +0200
@@ -23,9 +23,14 @@
     		{% endthumbnail %}
     			<div class="fragment-infos">
     				<a class="fa fa-eye" href="{% url 'annotation_detail' collection_name image_guid annotation.annotation_guid  %}">Voir</a>
-    				<p class="small">Créee par <strong>{{ annotation.author }}</strong></strong><p>
-    				<p class="small">Révisée par <strong>{{ annotation.current_revision.author }}</strong>
-    				le {{ annotation.current_revision.created|date:'d-m-Y' }}
+    				<p class="small">Créee par <strong>{{ annotation.author }}</strong>, dernière révision le {{ annotation.current_revision.created|date:'d-m-Y' }}<p>
+    				<p class="small">Contributeurs: 
+                    {% for contributor in annotation.stats.contributors %}
+                      {% if not forloop.last %}
+                                                 
+                      {% endif %}
+                        <strong>{{ contributor }}</strong>{% if not forloop.last %}, {% endif %}
+                    {% endfor %}
     				</p>
     			</div>
     	</li>
--- a/src/iconolab/urls.py	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/urls.py	Thu Jul 07 16:34:31 2016 +0200
@@ -13,6 +13,7 @@
     1. Import the include() function: from django.conf.urls import url, include
     2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
 """
+from django.core.urlresolvers import reverse_lazy
 from django.conf.urls import url, include
 from django.contrib import admin
 from . import views
@@ -23,6 +24,7 @@
 from django.contrib.staticfiles.urls import staticfiles_urlpatterns
 
 urlpatterns = [
+    url(r'^$', views.RedirectView.as_view(url=reverse_lazy("home"))),
     url(r'^admin/', admin.site.urls),
     url(r'^home$', views.GlobalHomepageView.as_view(), name="home"),
     url(r'^collections/(?P<collection_name>[a-z]+)$', views.CollectionHomepageView.as_view(), name='collection_home'), # Home fond
--- a/src/iconolab/views.py	Fri Jul 22 16:48:08 2016 +0200
+++ b/src/iconolab/views.py	Thu Jul 07 16:34:31 2016 +0200
@@ -341,7 +341,33 @@
                         'revision_guid': revision.revision_guid
                     }
                 )
-            )
+            )(request)
+        # Auto-accepts the revision only if the proper query arg is set and only if the revision parent is the current revision
+        if "auto_accept" in request.GET and request.GET["auto_accept"] in ["True", "true", "1", "yes"] and revision.parent_revision == annotation.current_revision:
+            annotation.validate_existing_revision(revision)
+            return RedirectView.as_view(
+                url=reverse('annotation_detail', 
+                    kwargs={
+                        'collection_name': collection.name, 
+                        'image_guid': image.image_guid, 
+                        'annotation_guid': annotation.annotation_guid
+                    }
+                )
+            )(request)
+        # Auto-reject the revision only if the proper query arg is set
+        print(request.GET)
+        if "auto_reject" in request.GET and request.GET["auto_reject"] in ["True", "true", "1", "yes"]:
+            annotation.reject_existing_revision(revision) 
+            return RedirectView.as_view(
+                url=reverse('annotation_detail', 
+                    kwargs={
+                        'collection_name': collection.name, 
+                        'image_guid': image.image_guid, 
+                        'annotation_guid': annotation.annotation_guid
+                    }
+                )
+            )(request)
+        
         context = self.get_context_data(**kwargs)
         context['collection'] = collection
         context['image'] = image