adding annotations list
authorHarris Baptiste <harris.baptiste@iri.centrepompidou.fr>
Thu, 23 Jun 2016 17:27:44 +0200
changeset 31 e34b70a00488
parent 30 7ff344b4bf6d
child 32 3ed91fed6dd8
adding annotations list
src/iconolab/fixtures/dev_initial_data.json
src/iconolab/migrations/0001_initial.py
src/iconolab/models.py
src/iconolab/static/iconolab/js/components/cutout/index.js
src/iconolab/static/iconolab/js/dist/bundle.js
src/iconolab/templates/iconolab/change_annotation.html
src/iconolab/templates/iconolab/detail_annotation.html
src/iconolab/templates/iconolab/detail_image.html
src/iconolab/templates/partials/image_annotations_list.html
src/iconolab/templatetags/iconolab_tags.py
src/iconolab/views.py
--- a/src/iconolab/fixtures/dev_initial_data.json	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/fixtures/dev_initial_data.json	Thu Jun 23 17:27:44 2016 +0200
@@ -68,7 +68,30 @@
 			"author": 1,
 			"created": "2016-03-24 14:13:44.913765+01"
 	    }
-	},{
+	},
+	{
+	    "model": "iconolab.Annotation",
+	    "pk": 2,
+	    "fields": {
+	    	"annotation_guid": "34ae39ae-a9a2-4736-bc59-ba6f00e37f51",
+			"image": 1,
+			"current_revision" : 2,
+			"author": 1,
+			"created": "2016-03-24 14:13:44.913765+01"
+	    }
+	},
+	{
+	    "model": "iconolab.Annotation",
+	    "pk": 3,
+	    "fields": {
+	    	"annotation_guid": "34ae39ae-a9a2-4736-bc59-ba6f00e37f53",
+			"image": 1,
+			"current_revision" : 3,
+			"author": 1,
+			"created": "2016-03-24 14:13:44.913765+01"
+	    }
+	},
+	{
 	    "model": "iconolab.AnnotationStats",
 	    "pk": 1,
 	    "fields": {
@@ -93,6 +116,35 @@
 			"state": 1,
 			"created": "2016-03-25 14:13:44.913765+01"
 	    }
+	},
+	{
+	    "model": "iconolab.AnnotationRevision",
+	    "pk": 2,
+	    "fields": {
+			"annotation": 2,
+	    	"revision_guid": "b14c8382-b136-42d0-abe1-b0a94f60d9d1",
+			"author": 1,
+			"title": "Une autre annotation sur Napoléon!",
+			"description": "ma nouvelle description",
+			"fragment": "M41.49797570850203,17.375C41.49797570850203,17.375,46.35627530364373,14.25,46.35627530364373,14.25C46.35627530364373,14.25,55.87044534412955,13.625,55.87044534412955,13.625C55.87044534412955,13.625,61.94331983805668,21.375,61.94331983805668,21.375C61.94331983805668,21.375,59.10931174089069,26.875,59.10931174089069,26.875C59.10931174089069,26.875,44.534412955465584,27.375,44.534412955465584,27.375C44.534412955465584,27.375,40.48582995951418,23.875,40.48582995951418,23.875C40.48582995951418,23.875,41.49797570850203,17.375,41.49797570850203,17.375 Z;FREE",
+			"state": 1,
+			"created": "2016-03-25 14:13:44.913765+01"
+	    }
+	},
+	{
+	    "model": "iconolab.AnnotationRevision",
+	    "pk": 3,
+	    "fields": {
+			"annotation": 3,
+	    	"revision_guid": "b14c8382-b136-42d0-abe1-b0a94f60d9d2",
+			"author": 1,
+			"title": "Ceci est ma nouvelle annotation",
+			"description": "C'est une autre description",
+			"fragment": "M12.955465587044534,23.625C12.955465587044534,23.625,9.7165991902834,17.75,9.7165991902834,17.75C9.7165991902834,17.75,4.65587044534413,12.125,4.65587044534413,12.125C4.65587044534413,12.125,5.870445344129554,4.25,5.870445344129554,4.25C5.870445344129554,4.25,6.680161943319838,1.125,6.680161943319838,1.125C6.680161943319838,1.125,12.753036437246964,1.625,12.753036437246964,1.625C12.753036437246964,1.625,13.157894736842104,9.375,13.157894736842104,9.375C13.157894736842104,9.375,16.194331983805668,13.625,16.194331983805668,13.625C16.194331983805668,13.625,22.267206477732792,17.125,22.267206477732792,17.125C22.267206477732792,17.125,28.74493927125506,22,28.74493927125506,22C28.74493927125506,22,24.493927125506072,25.75,24.493927125506072,25.75C24.493927125506072,25.75,12.955465587044534,23.625,12.955465587044534,23.625 Z;FREE",
+			"state": 1,
+			"created": "2016-03-25 14:13:44.913765+01"
+	    }
 	}
+
 	
 ]
\ No newline at end of file
--- a/src/iconolab/migrations/0001_initial.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/migrations/0001_initial.py	Thu Jun 23 17:27:44 2016 +0200
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Generated by Django 1.9.7 on 2016-06-21 12:07
+# Generated by Django 1.9.7 on 2016-06-22 10:22
 from __future__ import unicode_literals
 
 from django.conf import settings
--- a/src/iconolab/models.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/models.py	Thu Jun 23 17:27:44 2016 +0200
@@ -36,6 +36,9 @@
 		return self.name
 
 
+class Item(models.Model):
+	collection = models.ForeignKey(Collection, related_name="items")
+		
 class ItemMetadata(models.Model):
 	item = models.OneToOneField('Item', related_name='metadatas')
 	joconde_ref = models.CharField(max_length=20, null=False, blank=False, unique=True)
@@ -43,8 +46,7 @@
 	title = models.CharField(max_length=255)
 	description = models.CharField(max_length=255)
 
-class Item(models.Model):
-	collection = models.ForeignKey(Collection, related_name="items")
+
 
 class ImageStats(models.Model):
 	image = models.OneToOneField('Image', related_name='stats', blank=False, null=False)
--- a/src/iconolab/static/iconolab/js/components/cutout/index.js	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/static/iconolab/js/components/cutout/index.js	Thu Jun 23 17:27:44 2016 +0200
@@ -253,7 +253,6 @@
 	updatePath(paper);
 };
 
-
 var attachRectEvents = function (paper) {
 	if (readOnly) { return false; }
 
@@ -344,8 +343,11 @@
 		}
 
 		this.setDrawingMode(pathInfos[1]);
-		var pathData =pathInfos[0];
-
+		var pathData = pathInfos[0];
+		
+		if(!pathData.length) {
+			return;
+		}
 		/* deal with path nomalization x = ImageWith/MaxXBound*/
 		var xRatio = mainImage.width() / viewBoxBounds.X;
 		var yRatio = mainImage.height() / viewBoxBounds.Y;
@@ -361,7 +363,6 @@
 		if (path.search(/[z|Z]/gi) === -1 ) {
 			path += "Z";
 		}
-
 		if (pathInfos.length >= 2) {
 			if (pathInfos[1] === RECT_MODE) {
 				handleRectPath(path);
@@ -413,7 +414,14 @@
 		var path = "";
 		if (drawing_path) {
 			if (drawingMode === RECT_MODE) {
-				path = Snap.path.toAbsolute(drawing_path.getBBox().path).toString();
+				path = Snap.path.toAbsolute(drawing_path.realPath).toString();
+				var parentMatrix = drawing_path.transform();
+				console.log("local Matrix", drawing_path.transform());
+				console.log("drawing_path", drawing_path.getBBox());
+				console.log("chemin...", path);
+
+				paper.path(path);
+				console.log("...radical blaze...", drawing_path);
 			}
 			else {
 				path = drawing_path.attr('d');
@@ -426,10 +434,14 @@
 			new Error('ratio should be a number.');
 		}
 
+		if (!path.length) {
+			path = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE";
+			return path;
+		}
+
 		var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0);
 		path = Snap.path.map(path, normalizeMatrix).toString();
-		
-		/* save the type */
+				/* save the type */
 		var type = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE";
 		if (path.search(/[z|Z]/gi) === -1) {
 			path += " Z";	
@@ -454,7 +466,6 @@
 			onChangeCallback = config.onDrawingModeChange;
 		}
 
-		onChangeCallback 
 		if (!cutCanvas.length) {
 			var cutCanvas = jQuery('<svg version="1.1"></svg>').addClass('cut-canvas');
 			jQuery(config.wrapperId).append(cutCanvas);
--- a/src/iconolab/static/iconolab/js/dist/bundle.js	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/static/iconolab/js/dist/bundle.js	Thu Jun 23 17:27:44 2016 +0200
@@ -320,7 +320,6 @@
 		updatePath(paper);
 	};
 
-
 	var attachRectEvents = function (paper) {
 		if (readOnly) { return false; }
 
@@ -411,8 +410,11 @@
 			}
 
 			this.setDrawingMode(pathInfos[1]);
-			var pathData =pathInfos[0];
-
+			var pathData = pathInfos[0];
+			
+			if(!pathData.length) {
+				return;
+			}
 			/* deal with path nomalization x = ImageWith/MaxXBound*/
 			var xRatio = mainImage.width() / viewBoxBounds.X;
 			var yRatio = mainImage.height() / viewBoxBounds.Y;
@@ -428,7 +430,6 @@
 			if (path.search(/[z|Z]/gi) === -1 ) {
 				path += "Z";
 			}
-
 			if (pathInfos.length >= 2) {
 				if (pathInfos[1] === RECT_MODE) {
 					handleRectPath(path);
@@ -480,7 +481,14 @@
 			var path = "";
 			if (drawing_path) {
 				if (drawingMode === RECT_MODE) {
-					path = Snap.path.toAbsolute(drawing_path.getBBox().path).toString();
+					path = Snap.path.toAbsolute(drawing_path.realPath).toString();
+					var parentMatrix = drawing_path.transform();
+					console.log("local Matrix", drawing_path.transform());
+					console.log("drawing_path", drawing_path.getBBox());
+					console.log("chemin...", path);
+
+					paper.path(path);
+					console.log("...radical blaze...", drawing_path);
 				}
 				else {
 					path = drawing_path.attr('d');
@@ -493,10 +501,14 @@
 				new Error('ratio should be a number.');
 			}
 
+			if (!path.length) {
+				path = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE";
+				return path;
+			}
+
 			var normalizeMatrix = Snap.matrix(xRatio, 0, 0, yRatio, 0, 0);
 			path = Snap.path.map(path, normalizeMatrix).toString();
-			
-			/* save the type */
+					/* save the type */
 			var type = (drawingMode === RECT_MODE) ? ";RECT" : ";FREE";
 			if (path.search(/[z|Z]/gi) === -1) {
 				path += " Z";	
@@ -521,7 +533,6 @@
 				onChangeCallback = config.onDrawingModeChange;
 			}
 
-			onChangeCallback 
 			if (!cutCanvas.length) {
 				var cutCanvas = jQuery('<svg version="1.1"></svg>').addClass('cut-canvas');
 				jQuery(config.wrapperId).append(cutCanvas);
@@ -564,7 +575,7 @@
 /* 2 */
 /***/ function(module, exports, __webpack_require__) {
 
-	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_0__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
+	var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_LOCAL_MODULE_0__;/*** IMPORTS FROM imports-loader ***/
 	(function() {
 	var fix = module.exports=0;
 
--- a/src/iconolab/templates/iconolab/change_annotation.html	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templates/iconolab/change_annotation.html	Thu Jun 23 17:27:44 2016 +0200
@@ -8,7 +8,7 @@
 
 	<div id="drawing-zone" class="row" style="padding-top: 10px; border:1px solid orange">
 		
-		<div v-show='!formView' class="editor-wrapper col-md-12">
+		<div v-show='!formView' style="display:none" class="editor-wrapper col-md-12">
 			<div class='col-md-2'>
 				<ul class="form-drawing-wrapper list-inline">
 					<p class='form-drawing pullright'><strong>Type de dessin</strong></p>
@@ -21,7 +21,7 @@
 					
 					<li @click="clear" class='pull-md-right drawingModeBtn'><i class='fa fa-trash'></i> Effacer</li>
 
-					<li @click="save" class='pull-md-right drawingModeBtn'><i class='fa fa-plus'></i> Créer le fragment</li>
+					<li @click="showForm" class='pull-md-right drawingModeBtn infos info'><i class='fa fa-plus'></i> Valider</li>
 				</ul>
 			</div>
 			
@@ -33,6 +33,10 @@
 					{% endthumbnail %}
 				</div>
 			</div>
+			
+			<div class="col-md-2">
+				<a @click="cancel"><i class="fa fa-close"></i> Annuler</a>
+			</div>
 
 		</div>
 
@@ -49,7 +53,7 @@
 								<mask xmlns="http://www.w3.org/2000/svg" id="smallImage">
 									<rect x="0" y="0" width="{{ im.width }}", height="{{ im.height }}" fill="white"/>
 									<g v-bind:transform="transformMatrix">
-										<path v-bind:d="fragmentPath"></path>
+										<path v-el:current-path v-bind:d="fragmentPath"></path>
 									</g>
 								</mask>	
 							</defs>
@@ -89,8 +93,9 @@
         			<button type="submit" class="save btn btn-default">Enregister</button>
     			</form>
 			</div>
+			
+		</div>
 
-		</div>
 	</div>
 
 {% endblock %}
@@ -107,7 +112,7 @@
 				isRect: true,
 				normalizePath: "",
 				readOnly: false,
-				formView: false,
+				formView: true,
 				useClipPath: false,
 				transformMatrix: "",
 				fragmentPath: "",
@@ -117,6 +122,7 @@
 
 			init: function () {
 				var self = this;
+				this.initialDrawingMode = null;
 				this.drawingComponent = iconolab.initCutoutComponent({ 
 					wrapperId: '#iconolab-image-wrapper',
 						actionWrapper: '#action-wrapper',
@@ -127,11 +133,18 @@
 							});
 						}
 				});
+
+				this.$nextTick(function () {
+					this.showForm();	
+				});
 			},
 
 			methods: {
 
 				setDrawingMode: function (mode, updateComponent) {
+					if (!this.initialDrawingMode) {
+						this.initialDrawingMode = mode;//useful for cancel
+					}
 					var updateComponent = (typeof updateComponent === "boolean") ? updateComponent: true;
 					this.mode = this.$options['MODE_' + mode];
 					this.isRect = (this.mode === this.$options.MODE_RECT) ? true: false;
@@ -139,10 +152,18 @@
 						this.drawingComponent.setDrawingMode(this.mode);
 					}
 				},
+				
+				cancel: function () {
+					this.formView = true;
+					var currentPath = this.$els.currentPath.getAttribute("d");
+					if (!currentPath.length || !this.initialDrawingMode) { return; } {
+						currentPath += ";" + this.initialDrawingMode; 
+						this.drawingComponent.setPath(currentPath);
+					}
+				},
 
 				showEditor: function () {
 					this.formView = false;
-					console.log(this.$els.smallImage);
 				},
 
 				highLightZone: function () {
@@ -161,18 +182,15 @@
 					var normalizePath = this.drawingComponent.getPath();
 				},
 
-				save: function () {
+				showForm: function () {
 					this.normalizePath = this.drawingComponent.getPath();
 					var smallImage = this.$els.smallImage;
 					this.formView = true;
-					/* 100x = smallImageHeight && 100x=smallImageWidth | 100 = ViewBoxBound */
 					var xRatio = smallImage.width / 100;
 					var yRatio = smallImage.height / 100;
 					var transformMatrix = [xRatio, 0, 0, yRatio, 0, 0].join(',');
 					this.transformMatrix ="matrix(" + transformMatrix + ")";
 					this.fragmentPath = this.normalizePath.split(';')[0];
-					console.log(this.fragmentPath);
-					console.log(this.transformMatrix);
 				},
 
 				clear: function () {
--- a/src/iconolab/templates/iconolab/detail_annotation.html	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_annotation.html	Thu Jun 23 17:27:44 2016 +0200
@@ -7,6 +7,8 @@
 {% load iconolab_tags %}
 
 {% block content %}
+	
+	<a href="{% url 'image_detail' collection_name image_ref %}"><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">
@@ -18,7 +20,7 @@
 						<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="{{ annotation.current_revision.fragment }}" opacity="0.7" fill="orange"></path>
+								<path d="{{ annotation.current_revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
 							</g>
 
 						</svg>
@@ -38,5 +40,4 @@
 			</div>
 		</div>
 	</div>
-
 {% endblock %}
--- a/src/iconolab/templates/iconolab/detail_image.html	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templates/iconolab/detail_image.html	Thu Jun 23 17:27:44 2016 +0200
@@ -7,7 +7,17 @@
 {% load iconolab_tags %}
 
 {% block content %}
-<p>detail_image for {{image_ref}} in the collection {{collection_name}}</p>
-<a href="{% url 'annotation_create' collection_name image_ref %}">Create Annotation</a>
+
+<div class="row">
+	<div class="col-md-6 col-md-offset-3">
+		<a class="btn btn-link" href="{% url 'image_detail' collection_name image_ref %}"><i class="fa fa-plus"></i> Créer une nouvelle annotation</a>
+
+		{% thumbnail image.media "x800" crop="center" as im %}
+			<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
+		{% endthumbnail %}
+	</div>
+</div>
+
+{% include "partials/image_annotations_list.html" with annotation_list=annotation_list %}
 
 {% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/iconolab/templates/partials/image_annotations_list.html	Thu Jun 23 17:27:44 2016 +0200
@@ -0,0 +1,30 @@
+{% load thumbnail %}
+{% load iconolab_tags %}
+
+<ul class="annotation-list-wrapper list-inline">
+
+	<p><strong>Annotations de l'image</strong></p>
+
+	 {% for annotation in annotation_list %}
+	<li class="small-image-wrapper">
+		
+		<div class="fragment-container" style="position: relative">
+		{% thumbnail annotation.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="{{ annotation.current_revision.fragment|clean_path }}" opacity="0.7" fill="orange"></path>
+				</g>
+			</svg>
+			</div>
+		{% endthumbnail %}
+			<div class="fragment-infos">
+				<a class="fa fa-eye" href="{% url 'annotation_edit' collection_name image_ref annotation.annotation_guid  %}">Voir</a>
+				<p class="small">Créer 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>
+			</div>
+	</li>
+{% endfor %}
+</ul>
\ No newline at end of file
--- a/src/iconolab/templatetags/iconolab_tags.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/templatetags/iconolab_tags.py	Thu Jun 23 17:27:44 2016 +0200
@@ -16,6 +16,7 @@
 
 	return matrix
 
+@register.filter
 def clean_path(path):
 	if not len(path):
 		return ""
--- a/src/iconolab/views.py	Wed Jun 22 17:53:40 2016 +0200
+++ b/src/iconolab/views.py	Thu Jun 23 17:27:44 2016 +0200
@@ -27,6 +27,15 @@
 		context = super(ShowImageView, self).get_context_data(**kwargs)
 		context["collection_name"] = self.kwargs.get("collection_name", "")
 		context["image_ref"] = self.kwargs.get("image_ref", "")
+		context["annotation_list"] = []
+		try:
+			image = Image.objects.get(image_ref=context["image_ref"]) 
+			annotation_list = Annotation.objects.filter(image_id=image.id)
+			context["image"] = image
+			context["annotation_list"] = annotation_list
+		except Image.DoesNotExist:
+			return RedirectView.as_view(url=reverse("404error"))
+			
 		return render(request, 'iconolab/detail_image.html', context);