merge the changes of Camille
authorrougeronj
Fri, 22 May 2015 12:47:16 +0200
changeset 91 f7a844a9079e
parent 90 faf2cdb47813
child 92 fabc568d88d1
merge the changes of Camille
client/app/app.js
client/app/books/add_book_modal.html
client/app/books/book.html
client/app/books/books.html
client/app/books/books_controller.js
client/app/index.html
client/app/my_visit/add_modal_my_visit.html
client/app/my_visit/my_visit.css
client/app/my_visit/my_visit.html
client/app/my_visit/my_visit_controller.js
client/app/my_visit/my_visit_controller_test.js
client/app/my_visit/share_modal_my_visit.html
client/app/slides/slides.css
client/app/slideshow/slideshow.html
client/app/visites/add_book_modal.html
client/app/visites/add_modal_visites.html
client/app/visites/share_modal_visites
client/app/visites/visite.css
client/app/visites/visite.html
client/app/visites/visites.html
client/app/visites/visites_controller.js
client/app/visites/visites_controller_test.js
client/gulpfile.js
--- a/client/app/app.js	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/app.js	Fri May 22 12:47:16 2015 +0200
@@ -1,116 +1,130 @@
 (function(){
-	'use strict';
+    'use strict';
 
-	angular.module('ammico', [ 'ngRoute','ammicoHome', 'ammicoBooks', 'ammicoSlides', 'ammicoSlideshow', 'ammicoSearch', 'ammicoAuth', 'templates' ])
-	.config(function($routeProvider) {
-		$routeProvider.
-		when('/', {
-			controller: 'homeCtrl',
-			templateUrl: 'home/home.html',
-			authRequired: false
-		}).
-		when('/books', {
-			controller: 'booksCtrl',
-			templateUrl: 'books/books.html',
-			authRequired: true
-		}).
-		when('/books/:idBook', {
-			controller: 'bookCtrl',
-			templateUrl: 'books/book.html',
-			authRequired: true
-		}).
-		when('/slide/:idSlide', {
-			controller: 'slidesCtrl',
-			templateUrl: 'slides/slides.html',
-			authRequired: true
-		}).
-		when('/slideshow/', {
-			controller: 'slideshowCtrl',
-			templateUrl: 'slideshow/slideshow.html',
-			authRequired: true
-		}).
-		when('/slideshow/:iSlide', {
-			controller: 'slideshowCtrl',
-			templateUrl: 'slideshow/slideshow.html',
-			authRequired: true
-		}).
-		when('/search/:q', {
-			controller: 'searchCtrl',
-			templateUrl: 'search/search.html',
-			authRequired: true
-		}).
-		when('/auth/:action', {
-			controller: 'authCtrl',
-			templateUrl: 'home/home.html',
-			authRequired: false
-		}).
-		otherwise({
-			redirectTo: '/'
-		});
-	})
-	.run( function($rootScope, $location, $window, $http) {
-		$rootScope.globals = {};
-		if ($window.sessionStorage.token) {
-			$rootScope.globals.userLogged = true;
-			$http.defaults.headers.common.Authorization = 'Token ' + $window.sessionStorage.token;
-		}
-		$rootScope.$on( '$routeChangeStart', function(event, next) {
-			if (next.authRequired && !$rootScope.globals.userLogged) {
-				$location.path( '/auth/login' );
-			}
-		});
-	})
-	.service('searchApi', function($resource, context) {
-		this.searchResource = function(params){
-			return $resource(context.urls.searchUrl,  
-					{
-				callback: 'JSON_CALLBACK'
-					},
-					{
-						getJsonp: {
-							method: 'JSONP',
-							params: params,
-							isArray: false,
-							transformResponse: function(data){
-								// Transform meta list into meta dict
-								var nb = data.hits.length;
-								for(var i=0;i<nb;i++){
-									var nb_metas = data.hits[i].metas.length;
-									data.hits[i].metas_dict = {};
-									for(var j=0;j<nb_metas;j++){
-										if(typeof data.hits[i].metas[j].images==='undefined'){
-											data.hits[i].metas_dict[data.hits[i].metas[j].name] = data.hits[i].metas[j].value;
-										}
-										else{
-											data.hits[i].metas_dict.images = data.hits[i].metas[j].images[0].value;
-										}
-									}
-								}
-								return data;
-							}
-						}
-					});
-		};
-	})
-	.service('ammicoApi', function($resource, context, $sce) {
-		this.listBooks = $resource(context.urls.ammicoUrl+'/books');
-		this.book = $resource(context.urls.ammicoUrl+'/books/:idBook', {idBook:'@idBook'});
-		this.order = $resource(context.urls.ammicoUrl+'/books/:idBook/order', {idBook:'@idBook'});
-		this.booksSlides = $resource(context.urls.ammicoUrl+'/books/:idBook/slides', {idBook:'@idBook'});
-		this.listSlides= $resource(context.urls.ammicoUrl+'/slides');
-		this.slide = $resource(context.urls.ammicoUrl+'/slides/:idSlide', {idSlide:'@idSlide'});
-		this.sanitizeUrls = function(data){
-			data.details.audio = $sce.trustAsResourceUrl(data.details.audio);
-			data.details.video = $sce.trustAsResourceUrl(data.details.video);
-			data.audio = $sce.trustAsResourceUrl(data.audio);
-			data.video = $sce.trustAsResourceUrl(data.video);
-			return data;
-		};
-	})
-	.service('authApi', function($resource, context) {
-		this.login = $resource(context.urls.ammicoUrl+'/auth/api-token-auth');
-		this.logout = $resource(context.urls.ammicoUrl+'/auth/logout');
-		this.user = $resource(context.urls.ammicoUrl+'/auth/user');
-		this.test = $resource(context.urls.ammicoUrl+'/auth/auth');
-	});
+    angular.module('ammico', [ 'ngRoute','ammicoHome', 'ammicoMyvisit', 'ammicoBooks', 'ammicoVisites', 'ammicoSlides', 'ammicoSlideshow', 'ammicoSearch', 'ammicoAuth', 'templates' ])
+    .config(function($routeProvider) {
+        $routeProvider.
+        when('/', {
+            controller: 'homeCtrl',
+            templateUrl: 'home/home.html',
+            authRequired: false
+        }).
+        when('/my_visit', {
+            controller: 'my_visitCtrl',
+            templateUrl: 'my_visit/my_visit.html',
+            authRequired: true
+        }).
+        when('/books', {
+            controller: 'booksCtrl',
+            templateUrl: 'books/books.html'
+        }).
+        when('/books/:idBook', {
+            controller: 'bookCtrl',
+            templateUrl: 'books/book.html',
+            authRequired: true
+        }).
+        when('/visites', {
+            controller: 'visitesCtrl',
+            templateUrl: 'visites/visites.html',
+            authRequired: true
+        }).
+        when('/visites/:idVisit', {
+            controller: 'visiteCtrl',
+            templateUrl: 'visites/visite.html',
+            authRequired: true
+        }).
+        when('/slide/:idSlide', {
+            controller: 'slidesCtrl',
+            templateUrl: 'slides/slides.html',
+            authRequired: true
+        }).
+        when('/slideshow/', {
+            controller: 'slideshowCtrl',
+            templateUrl: 'slideshow/slideshow.html',
+            authRequired: true
+        }).
+        when('/slideshow/:iSlide', {
+            controller: 'slideshowCtrl',
+            templateUrl: 'slideshow/slideshow.html',
+            authRequired: true
+        }).
+        when('/search/:q', {
+            controller: 'searchCtrl',
+            templateUrl: 'search/search.html',
+            authRequired: true
+        }).
+        when('/auth/:action', {
+            controller: 'authCtrl',
+            templateUrl: 'home/home.html',
+            authRequired: false
+        }).
+        otherwise({
+            redirectTo: '/'
+        });
+    })
+    .run( function($rootScope, $location, $window, $http) {
+        $rootScope.globals = {};
+        if ($window.sessionStorage.token) {
+            $rootScope.globals.userLogged = true;
+            $http.defaults.headers.common.Authorization = 'Token ' + $window.sessionStorage.token;
+        }
+        $rootScope.$on( '$routeChangeStart', function(event, next) {
+            if (next.authRequired && !$rootScope.globals.userLogged) {
+                $location.path( '/auth/login' );
+            }
+        });
+    })
+    .service('searchApi', function($resource, context) {
+        this.searchResource = function(params){
+            return $resource(context.urls.searchUrl,  
+                    {
+                callback: 'JSON_CALLBACK'
+                    },
+                    {
+                        getJsonp: {
+                            method: 'JSONP',
+                            params: params,
+                            isArray: false,
+                            transformResponse: function(data){
+                                // Transform meta list into meta dict
+                                var nb = data.hits.length;
+                                for(var i=0;i<nb;i++){
+                                    var nb_metas = data.hits[i].metas.length;
+                                    data.hits[i].metas_dict = {};
+                                    for(var j=0;j<nb_metas;j++){
+                                        if(typeof data.hits[i].metas[j].images==='undefined'){
+                                            data.hits[i].metas_dict[data.hits[i].metas[j].name] = data.hits[i].metas[j].value;
+                                        }
+                                        else{
+                                            data.hits[i].metas_dict.images = data.hits[i].metas[j].images[0].value;
+                                        }
+                                    }
+                                }
+                                return data;
+                            }
+                        }
+                    });
+        };
+    })
+    .service('ammicoApi', function($resource, context, $sce) {
+        this.listBooks = $resource(context.urls.ammicoUrl+'/books');
+        this.book = $resource(context.urls.ammicoUrl+'/books/:idBook', {idBook:'@id'});
+        this.order = $resource(context.urls.ammicoUrl+'/books/:idBook/order', {idBook:'@id'});
+        this.booksSlides = $resource(context.urls.ammicoUrl+'/books/:idBook/slides', {idBook:'@id'});
+        this.listSlides= $resource(context.urls.ammicoUrl+'/slides');
+        this.slide = $resource(context.urls.ammicoUrl+'/slides/:idSlide', {idSlide:'@id'});
+        this.sanitizeUrls = function(data){
+            data.details.audio = $sce.trustAsResourceUrl(data.details.audio);
+            data.details.video = $sce.trustAsResourceUrl(data.details.video);
+            data.audio = $sce.trustAsResourceUrl(data.audio);
+            data.video = $sce.trustAsResourceUrl(data.video);
+            return data;
+        };
+    })
+    .service('authApi', function($resource, context) {
+        this.login = $resource(context.urls.ammicoUrl+'/auth/api-token-auth');
+        this.logout = $resource(context.urls.ammicoUrl+'/auth/logout');
+        this.user = $resource(context.urls.ammicoUrl+'/auth/user');
+        this.test = $resource(context.urls.ammicoUrl+'/auth/auth');
+    });
 })();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/books/add_book_modal.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,24 @@
+<div class="modal-header ng-scope">
+	<h3 class="modal-title">Vous voulez partager ce book ? </h3>
+</div>
+
+<div class="modal-body ng-scope">
+	<ul class="row ">
+		Les books de vos visites:
+		<li class="" ng-repeat="i in books | filter:{parent_visit:'!null'}:filter:{ parent_visit: 'null', idArticle: 'null' }">
+			<div>
+				<a ng-click="addToBook(i.id)">{{ i.title }}</a>
+			</div>
+		</li>
+		Autres Books:
+		<li class="" ng-repeat="i in books | filter:{ parent_visit: 'null', idArticle: 'null' }">
+			<div>
+				<a ng-click="addToBook(i.id)">{{ i.title }}</a>
+			</div>
+		</li>
+	</ul>
+</div>
+
+<div class="modal-footer ng-scope">
+	<button ng-click="cancel()" class="btn btn-warning">Cancel</button>
+</div>
\ No newline at end of file
--- a/client/app/books/book.html	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/books/book.html	Fri May 22 12:47:16 2015 +0200
@@ -1,14 +1,31 @@
-<p>Books {{idBook}}&nbsp;:</p>
+<accordion close-others="false"> 
+	<accordion-group is-open=true>
+		<accordion-heading>  
+			<a class="title" ng-click="$event.stopPropagation();" href="#/books/{{ parentBook.id }}">{{ parentBook.title }}</a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation();"><span class="glyphicon glyphicon-share"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation();"><span class="glyphicon glyphicon-cog"></span></a>
+			<a class="pull-right" ng-click="$event.stopPropagation();" href="#/slideshow/{{ parentBook.id }}"><span class="glyphicon glyphicon-eye-open"></span></a>
+		</accordion-heading>
+            
+		<a class="nbrObjects">{{parentBook.slides.length}} objets</a>
+        <ul ui-sortable="sortableOptions" ng:model="parentBook.slides" class="list-unstyled list-inline gallery container">
+			<li class="col-md-2 item" ng-repeat="i in parentBook.slides">
+	            <div class="img-ctn">
+                	<img class="img img-responsive image" ng-src="{{ i.details.images[0] }}" />
+	                <p>{{ i.details.title }}</p>
+	
+                    <div class="gallery-buttons">
+						<a class="btn btn-default" href="#/slide/{{ i.id }}"><span class="glyphicon glyphicon-pencil"></span></a>
+						<a class="btn btn-default" ng-click="toggleFavorite($index)"><span ng-class="{'glyphicon-star': i.favorite, 'glyphicon-star-empty': !i.favorite}" class="glyphicon"></span></a>
+						<a class="btn btn-default" ng-click="toggleModal($index)"><span class="glyphicon glyphicon-plus"></span></a>
+						<a class="btn btn-default" ng-click="deleteItem($index)"><span class="glyphicon glyphicon-trash"></span></a>
+					</div>
+				</div>
+			</li>
+		</ul>
 
-<ul ui-sortable="sortableOptions" ng:model="slides" class="list-unstyled list-inline gallery container">
-  <li class="col-md-3 item" ng-repeat="i in slides">
-    <div class="img-ctn">
-        <img class="img img-responsive image" ng-src="{{ i.details.images[0] }}" />
-        <p>{{ i.details.title }}</p>
-        <div class="gallery-buttons">
-          <a class="btn btn-default" href="#/slide/{{ i.id }}"><span class="glyphicon glyphicon-pencil"></span></a>
-          <a class="btn btn-default" ng-click="deleteItem($index)"><span class="glyphicon glyphicon-trash"></span></a>
-        </div>
-    </div>
-  </li>
-</ul>
+		<div class="book in books | filter:{ id: parentBook.parent_visit }:true">
+			{{book.title}}
+		</div>
+	</accordion-group>
+</accordion>
--- a/client/app/books/books.html	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/books/books.html	Fri May 22 12:47:16 2015 +0200
@@ -1,27 +1,50 @@
-<p>Liste des books&nbsp;:</p>
+
 
 <accordion close-others="false">
-	<accordion-group ng-repeat="parentBook in books | filter:{ parent_visit: 'null', idArticle: '!null' }" is-open=true>
+	<accordion-group ng-repeat="parentBook in books | filter:{ parent_visit: '!null', idArticle: 'null' }" is-open=true>
+
 		<accordion-heading>
-			{{ parentBook.title }}
-			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); addBook(parentBook.id)"><span class="glyphicon glyphicon-plus"></span></a>
-            <a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); edit()"><span class="glyphicon glyphicon-wrench"></span></a>
-            <a class="pull-right" ng-click="$event.stopPropagation();" href="#/slideshow/{{ parentBook.id }}"><span class="glyphicon glyphicon-eye-open"></span></a>
+
+			<a class="title" ng-click="$event.stopPropagation();" href="#/books/{{ parentBook.id }}">{{ parentBook.title }}</a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); addBook(parentBook.id)"><span class="glyphicon glyphicon-share"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation();"><span class="glyphicon glyphicon-cog"></span></a>
+			<a class="pull-right" ng-click="$event.stopPropagation();" href="#/slideshow/{{ parentBook.id }}"><span class="glyphicon glyphicon-eye-open"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); addBook(parentBook.id)">Nouveau Book</a>
+		
         </accordion-heading>
+
+        <a class="nbrObjects">{{parentBook.slides.length}} objets</a>
+        
         <div class="list-books" ng-repeat="childBook in books | filter:{ parent_visit: parentBook.id }:true">
 		        <a href="#/books/{{ childBook.id }}">{{ childBook.title }}</a>
 		        <a class="pull-right" ng-click="deleteItem(childBook)"><span class="glyphicon glyphicon-minus"></span></a>
         </div>
+        <ul ng:model="slides" class="list-unstyled list-inline gallery container">
+				  <li class="col-md-2 item" ng-repeat="i in parentBook.slides | limitTo : 5 ">
+				    <div class="img-ctn">
+				        <img class="img img-responsive image" ng-src="{{ i.details.images[0] }}" />
+				        <p>{{ i.details.title }}</p>
+
+				        <div class="gallery-buttons">
+				          <a class="btn btn-default" href="#/slide/{{ i.id }}"><span class="glyphicon glyphicon-pencil"></span></a>
+				          <a class="btn btn-default" ng-click=""><span class="glyphicon glyphicon-heart"></span></a>
+				          <a class="btn btn-default" ng-click="toggleModal($index)"><span class="glyphicon glyphicon-plus"></span></a>
+				          <a class="btn btn-default" ng-click="deleteItem($index)"><span class="glyphicon glyphicon-trash"></span></a>
+
+				        </div>
+				    </div>
+				<!-- </li> -->
+	    </ul>
+
+			<div ng-repeat="book in books | filter:{ id: parentBook.parent_visit }:true" >
+					{{book.title }}
+			</div>
+	</div>
+ 
+		
+
 	</accordion-group>
-	<accordion-group is-open=true>
-		<accordion-heading>
-			Autres Books
-		</accordion-heading>
-		<div class="list-books" ng-repeat="childBook in books | filter:{ parent_visit: 'null', idArticle: 'null' }">
-		        <a href="#/books/{{ childBook.id }}">{{ childBook.title }}</a>
-		        <a class="pull-right" ng-click="deleteItem(childBook)"><span class="glyphicon glyphicon-minus"></span></a>
-        </div>
-	</accordion-group>
+	
 </accordion>
 
 <a class="btn btn-default" ng-click="addBook()"><span class="glyphicon glyphicon-plus"></span></a>
\ No newline at end of file
--- a/client/app/books/books_controller.js	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/books/books_controller.js	Fri May 22 12:47:16 2015 +0200
@@ -7,7 +7,30 @@
 			data.sort(function (a, b) {
 				return a.date < b.date;
 			});
+
+			for (var i = 0; i < data.length; i++) {
+		    	if (data[i].idArticle === null){
+		    		data[i].slides = ammicoApi.booksSlides.query({idBook:data[i].id, format:'json'});
+		    	}
+			}	
 		});
+
+		$scope.toggleModal = function (index) {
+
+			var modalInstance = $modal.open({
+				templateUrl: 'books/add_book_modal.html',
+				controller: 'ModalAddBookCtrl',
+				size: 'sm'
+			});
+
+			modalInstance.result.then(function (idBook) {
+				var newSlide = {
+					book: idBook,
+					idInventory: $scope.results.hits[index].metas_dict.inventorynumber
+				};
+				ammicoApi.listSlides.save(newSlide);
+			});
+		};
 		
 		$scope.searchSubmit = function(){
 			$location.path('/search/' + $scope.q);
@@ -36,15 +59,43 @@
 			}
 		};
 	})
-	.controller('bookCtrl', function($scope, ammicoApi, $routeParams) {
-		$scope.slides = ammicoApi.booksSlides.query({idBook:$routeParams.idBook, format:'json'}, function(data){
-			data.sort(function (a, b) {
-				return a.orderIndex > b.orderIndex;
+
+	.controller('bookCtrl', function($scope, $location, ammicoApi, $routeParams, $modal) {
+		$scope.parentBook = ammicoApi.book.get({idBook:$routeParams.idBook, format:'json'}, function(data){
+			data.slides = ammicoApi.booksSlides.query({idBook: data.id, format:'json'}, function(data){
+				data.sort(function (a, b) {
+					return a.orderIndex > b.orderIndex;
+				});
 			});
 		});
+		
+		$scope.toggleFavorite = function (index) {
+
+		    $scope.parentBook.slides[index].favorite = !$scope.parentBook.slides[index].favorite;
+		    $scope.parentBook.slides[index].$save({format:'json'});
+		    //$scope.slide.$save({idSlide:$scope.slide.id, format:'json'});
+        };
+
+		$scope.toggleModal = function (index) {
+
+			var modalInstance = $modal.open({
+				templateUrl: 'books/add_book_modal.html',
+				controller: 'ModalAddBookCtrl',
+				size: 'sm'
+			});
+
+			modalInstance.result.then(function (idBook) {
+				var newSlide = {
+					book: idBook,
+					idInventory: $scope.results.hits[index].metas_dict.inventorynumber
+				};
+				ammicoApi.listSlides.save(newSlide);
+			});
+		};
+
 		$scope.sortableOptions = {
 				stop: function() {
-					var order = $scope.slides.map(function(i){
+					var order = $scope.parentBook.slides.map(function(i){
 						return i.id;
 					});
 					ammicoApi.order.save({idBook:$routeParams.idBook}, {order: order});
@@ -52,17 +103,18 @@
 		};
 
 		$scope.deleteItem = function(i){
-			if(0<=i && i<$scope.slides.length){
-				if(window.confirm('Êtes-vous sûr(e) de vouloir effacer cet élément ? Cette action est irrémédiable.')){
-					ammicoApi.slide.delete({idSlide: $scope.slides[i].id}, function(){
-						$scope.slides.splice(i, 1);
-					},
-					function(error) {
-						if (error.status === 404){
-							$scope.slides.splice(i, 1);
-						}
-					});
-				}
+		    if(window.confirm('Êtes-vous sûr(e) de vouloir effacer cet élément ? Cette action est irrémédiable.')){
+		        $scope.parentBook.slides[i].$delete();
+			//if(0<=i && i<$scope.slides.length){
+//					ammicoApi.slide.delete({idSlide: $scope.slides[i].id}, function(){
+//						$scope.slides.splice(i, 1);
+//					},
+//					function(error) {
+//						if (error.status === 404){
+//							$scope.slides.splice(i, 1);
+//						}
+//					});
+//				}
 			}
 		};
 	})
@@ -75,6 +127,16 @@
 		};
 		$scope.cancel = function () {
 			$modalInstance.dismiss('cancel');
+		}
+		;
+		$scope.books = ammicoApi.listBooks.query({format:'json'});
+		
+		$scope.addToBook = function(idBook){
+			$modalInstance.close(idBook);
+		};
+
+		$scope.cancel = function () {
+			$modalInstance.dismiss('cancel');
 		};
 	});
 })();
--- a/client/app/index.html	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/index.html	Fri May 22 12:47:16 2015 +0200
@@ -23,7 +23,7 @@
             <span class="icon-bar"></span>
             <span class="icon-bar"></span>
           </button>
-          <a class="navbar-brand logo" href="#/">
+          <a class="navbar-brand" id="logo" href="#/">
           	<!-- build:imgLogo -->
           	<img src="img/ammico_logo_small.png">
           	<!-- endbuild -->
@@ -32,8 +32,9 @@
         <div class="collapse navbar-collapse">
           <ul class="nav navbar-nav" ng-controller="routeClassCtrl">
             <li ng-class="{active:isActive('/')}"><a href="#/">Home</a></li>
-            <li ng-class="{active:isActive('/books')}"><a href="#/books">Books</a></li>
-            <li ng-class="{active:isActive('/slideshow')}"><a href="#/slideshow">Diaporama</a></li>
+            <li ng-class="{active:isActive('/my_visit')}"><a href="#/my_visit">Ma dernière Visite</a></li>
+            <li ng-class="{active:isActive('/visites')}"><a href="#/visites">Mes Visites</a></li>
+            <li ng-class="{active:isActive('/books')}"><a href="#/books">Mes Books</a></li>
           </ul>
           <ul class="nav navbar-nav navbar-right" ng-controller="routeClassCtrl">
             <li ng-hide="globals.userLogged" ng-class="{active:isActive('/login')}"><a href="#/auth/login">Login</a></li>
@@ -80,7 +81,7 @@
               record: angular.fromJson('{"record": "record value"}'),
               urls: {
                   base_static: "./",
-                  ammicoUrl: "http://127.0.0.1:8000/ammico",
+                  ammicoUrl: "http://0.0.0.0:8080/ammico",
                   searchUrl: "http://ammico.labs.exalead.com/search-api"
               }
           });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/my_visit/add_modal_my_visit.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,14 @@
+<div class="modal-header ng-scope">
+	<h3 class="modal-title">Ajouter un nouveau Book</h3>
+</div>
+
+<form ng-submit="add()" novalidate>
+	<div class="modal-body ng-scope">
+		<input type="text" class="form-control" ng-model='title' placeholder="Titre"></input>
+	</div>
+	
+	<div class="modal-footer ng-scope">
+		<button type="button" ng-click="cancel()" class="btn btn-warning">Cancel</button>
+		<button type="submit" class="btn btn-primary">Create</button>
+	</div>	
+</form>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/my_visit/my_visit.css	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,65 @@
+.gallery .item {
+  overflow:hidden; position:relative; height: 250px; padding: 5px;
+}
+
+.img-ctn {
+    height: 100%; width: 100%; border: 1px solid #DDD; padding: 5px; overflow: hidden;
+}
+
+.img-ctn:hover {
+    background-color: #DDD;
+}
+
+.img-ctn p {
+    background-color: #ddd;
+    bottom: -5px;
+    display: none;
+    padding: 2px 5px;
+    position: absolute;
+    width: calc(100% - 22px);
+}
+
+.img-ctn:hover p, .img-ctn:hover .gallery-buttons {
+    display: block;
+}
+
+.gallery .item img {
+    margin: 0 auto;
+    max-height: 100%;
+}
+
+.gallery-buttons{
+	display: none;
+    position: absolute;
+    right: 10px;
+    top: 10px;
+}
+
+.subtitle {
+    border-top: 1px solid #000;
+    border-bottom: 1px dotted #000;
+    margin-top: 20px;
+    padding: 6px 0 10px;
+}
+
+.add-book{
+	padding:20px;
+}
+.add-book input{
+	margin-bottom: 10px;
+}
+
+.accordion-toggle .glyphicon{
+	font-size: 17px;
+	margin-left:10px;
+}
+
+.list-books:nth-child(odd){
+	background-color:#f8f8f8;
+}
+
+.panel-title {
+    height: 15px;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/my_visit/my_visit.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,33 @@
+
+
+<accordion close-others="false">
+  <accordion-group ng-repeat="parentBook in books | filter:{ parent_visit: 'null', idArticle: '!null' } | orderBy: 'date' | limitTo : 1" is-open=true>
+    <accordion-heading>
+
+      <a class="title" ng-click="$event.stopPropagation();" href="#/my_visit/{{parentBook.id}}">{{ parentBook.title }}</a>
+      <a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); share($index)"><span class="glyphicon glyphicon-share"></span></a> 
+      <a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); edit()"><span class="glyphicon glyphicon-cog"></span></a>
+      <a class="pull-right" ng-click="$event.stopPropagation();" href="#/slideshow/{{ parentBook.id }}"><span class="glyphicon glyphicon-eye-open"></span></a>
+      <a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); addBook(parentBook.id)">Créer un Book</a>
+      
+    </accordion-heading>
+        <a class="nbrObjects">{{parentBook.slides.length}} objets</a>
+
+        <ul ng:model="slides" class="list-unstyled list-inline gallery container">
+          <li class="col-md-2 item" ng-repeat="i in parentBook.slides "> 
+            <div class="img-ctn">
+                <img class="img img-responsive image" ng-src="{{ i.details.images[0] }}"/>
+                <p>{{ i.details.title }}</p>
+                <div class="gallery-buttons">
+                 
+                  <a class="btn btn-default" ng-click="deleteItem($index)"><span class="glyphicon glyphicon-heart"></span></a>
+                  <a class="btn btn-default" ng-click="deleteItem($index)"><span class="glyphicon glyphicon-plus"></span></a>
+                 
+                </div>
+            </div>
+          </li>
+      </ul>
+  </accordion-group>
+</accordion>
+
+<a class="btn btn-default" ng-click="addBook()"><span class="glyphicon glyphicon-plus"></span></a>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/my_visit/my_visit_controller.js	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,67 @@
+(function(){
+	'use strict';
+
+	angular.module('ammicoMyvisit',['ngRoute', 'ui.sortable'])
+	.controller('my_visitCtrl', function($scope, $location, $modal, ammicoApi){
+
+		//get list book
+		$scope.books = ammicoApi.listBooks.query({format:'json'}, function(data){
+			data.sort(function (a, b) {
+				return a.date < b.date;
+			});
+
+			for (var i = 0; i < data.length; i++) {
+		    	if (data[i].idArticle){
+		    		data[i].slides = ammicoApi.booksSlides.query({idBook:data[i].id, format:'json'});
+		    	}
+			}	
+		});
+
+		$scope.addBook = function (idParent) {
+			$modal.open({
+				templateUrl: 'my_visit/add_modal_my_visit.html',
+				controller: 'ModalAddMyvisitCtrl'
+			}).result.then(function (title) {
+				//add book with the title written in the modal
+				ammicoApi.listBooks.save({idParent:idParent, title: title}, function(newBook){
+					$scope.books.push(newBook);
+				});
+			});
+		};
+
+
+		$scope.share = function (idParent) {
+			$modal.open({
+				templateUrl: 'my_visit/share_modal_my_visit.html',
+				controller: 'ModalAddMyvisitCtrl'
+			}).result.then(function (title) {
+				//add book with the title written in the modal
+				ammicoApi.slidesBook.query({idParent:idParent, title: title}, function(newBook){
+					$scope.books(newBook);
+				});
+			});
+		};
+
+		
+	})
+
+	.controller('ModalAddMyvisitCtrl', function ($scope, ammicoApi, $modalInstance) {
+
+		$scope.add = function(){
+			$modalInstance.close($scope.title);
+//			ammicoApi.listBooks.save({title: $scope.title}, function(newBook){
+//			});
+		};
+		$scope.cancel = function () {
+			$modalInstance.dismiss('cancel');
+		};
+		$scope.share = function () {
+			$modalInstance($scope.book);
+		};
+	});
+
+	
+
+
+})();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/my_visit/my_visit_controller_test.js	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,7 @@
+'use strict';
+
+describe("mavisite_controller_test", function(){
+    it("should assert something",function(){
+        expect(true).toBe(true);
+    })
+})
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/my_visit/share_modal_my_visit.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,16 @@
+<div class="modal-header ng-scope">
+	<h3 class="modal-title">Où souhaitez-vous partager ce book ?</h3>
+</div>
+
+<form ng-submit="share()" novalidate>
+	<div class="modal-body ng-scope">
+
+<a class="btn btn-social-icon btn-twitter">
+    <i class="fa fa-twitter"></i>
+  </a>
+
+	<div class="modal-footer ng-scope">
+		<button type="button" ng-click="cancel()" class="btn btn-warning">Cancel</button>
+		<button type="submit" class="btn btn-primary">Create</button>
+	</div>	
+</form>
\ No newline at end of file
--- a/client/app/slides/slides.css	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/slides/slides.css	Fri May 22 12:47:16 2015 +0200
@@ -16,7 +16,7 @@
 
 .slide-content{
 	padding:10px 0;
-	height: 524px;
+	height: 400px;
 }
 
 .media{
--- a/client/app/slideshow/slideshow.html	Fri May 22 12:37:37 2015 +0200
+++ b/client/app/slideshow/slideshow.html	Fri May 22 12:47:16 2015 +0200
@@ -7,7 +7,7 @@
 			<slide ng-repeat="slide in slideshow" active="slide.active">
 				<div class="container slide-content">
 					<div class="col-md-7 media">
-						<img ng-if="slide.details.images" ng-src="{{ slide.details.images }}" style="margin: auto;">
+						<img ng-if="slide.details.images[0]" ng-src="{{ slide.details.images[0] }}" style="margin: auto;">
 						<audio ng-if="slide.details.audio" ng-src="{{ slide.details.audio }}" style="margin: auto; controls loop"></audio>
 						<video ng-if="slide.details.video" ng-src="{{ slide.details.video }}" style="margin: auto;" controls></video>
 					</div>
@@ -36,7 +36,7 @@
 		<ul class="list-unstyled list-inline row insight" >
 			<li class="col-md-2 item" ng-repeat="slide in slideshow">
 				<div class="img-ctn" ng-click="showSlide($index)">
-				    <img class="img img-responsive image" ng-src="{{ slide.details.images }}" />
+				    <img class="img img-responsive image" ng-src="{{ slide.details.images[0] }}" />
 				    <p>{{ slide.details.title }}</p>
 				</div>
 			</li>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/add_book_modal.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,24 @@
+<div class="modal-header ng-scope">
+	<h3 class="modal-title">A quel Book ajouter cet element ?</h3>
+</div>
+
+<div class="modal-body ng-scope">
+	<ul class="row ">
+		Les books de vos visites:
+		<li class="" ng-repeat="i in books | filter:{parent_visit:'!null'}:filter:{ parent_visit: 'null', idArticle: 'null' }">
+			<div>
+				<a ng-click="addToBook(i.id)">{{ i.title }}</a>
+			</div>
+		</li>
+		Autres Books:
+		<li class="" ng-repeat="i in books | filter:{ parent_visit: 'null', idArticle: 'null' }">
+			<div>
+				<a ng-click="addToBook(i.id)">{{ i.title }}</a>
+			</div>
+		</li>
+	</ul>
+</div>
+
+<div class="modal-footer ng-scope">
+	<button ng-click="cancel()" class="btn btn-warning">Cancel</button>
+</div>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/add_modal_visites.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,14 @@
+<div class="modal-header ng-scope">
+	<h3 class="modal-title">Ajouter un nouveau Book</h3>
+</div>
+
+<form ng-submit="add()" novalidate>
+	<div class="modal-body ng-scope">
+		<input type="text" class="form-control" ng-model='title' placeholder="Titre"></input>
+	</div>
+	
+	<div class="modal-footer ng-scope">
+		<button type="button" ng-click="cancel()" class="btn btn-warning">Cancel</button>
+		<button type="submit" class="btn btn-primary">Create</button>
+	</div>	
+</form>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/share_modal_visites	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,14 @@
+<div class="modal-header ng-scope">
+	<h3 class="modal-title">Où souhaitez-vous partager ce book ?</h3>
+</div>
+
+<form ng-submit="share()" novalidate>
+	<div class="modal-body ng-scope">
+
+
+
+	<div class="modal-footer ng-scope">
+		<button type="button" ng-click="cancel()" class="btn btn-warning">Cancel</button>
+		<button type="submit" class="btn btn-primary">Create</button>
+	</div>	
+</form>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/visite.css	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,63 @@
+.gallery .item {
+  overflow:hidden; position:relative; height: 250px; padding: 5px;
+}
+
+.img-ctn {
+    height: 100%; width: 100%; border: 1px solid #DDD; padding: 5px; overflow: hidden;
+}
+
+.img-ctn:hover {
+    background-color: #DDD;
+}
+
+.img-ctn p {
+    background-color: #ddd;
+    bottom: -5px;
+    display: none;
+    padding: 2px 5px;
+    position: absolute;
+    width: calc(100% - 22px);
+}
+
+.img-ctn:hover p, .img-ctn:hover .gallery-buttons {
+    display: block;
+}
+
+.gallery .item img {
+    margin: 0 auto;
+    max-height: 100%;
+}
+
+.gallery-buttons{
+	display: none;
+    position: absolute;
+    right: 10px;
+    top: 10px;
+}
+
+.subtitle {
+    border-top: 1px solid #000;
+    border-bottom: 1px dotted #000;
+    margin-top: 20px;
+    padding: 6px 0 10px;
+}
+
+.add-book{
+	padding:20px;
+}
+.add-book input{
+	margin-bottom: 10px;
+}
+
+.accordion-toggle .glyphicon{
+	font-size: 17px;
+	margin-left:10px;
+}
+
+.list-books:nth-child(odd){
+	background-color:#f8f8f8;
+}
+
+.col-md-2 {
+    width : 19%;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/visite.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,26 @@
+ <accordion close-others="false">
+	<accordion-group is-open=true>
+		<accordion-heading>  
+			<a class="title" ng-click="$event.stopPropagation();" href="#/visites/{{ parentBook.id }}">{{ parentBook.title }}</a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation();"><span class="glyphicon glyphicon-share"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation();"><span class="glyphicon glyphicon-cog"></span></a>
+			<a class="pull-right" ng-click="$event.stopPropagation();" href="#/slideshow/{{ parentBook.id }}"><span class="glyphicon glyphicon-eye-open"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); addBook(parentBook.id)">Créer un Book</a>
+		</accordion-heading>
+		
+		<a class="nbrObjects">{{parentBook.slides.length}} objets</a>
+		
+		<ul ui-sortable="sortableOptions" ng:model="slides" class="list-unstyled list-inline gallery container">
+			<li class="col-md-2 item" ng-repeat="i in slides">
+				<div class="img-ctn">
+					<img class="img img-responsive image" ng-src="{{ i.details.images[0] }}" />
+					<p>{{ i.details.title }}</p>
+					<div class="gallery-buttons">
+						<a class="btn btn-default" href="#/slide/{{ i.id }}"><span class="glyphicon glyphicon-heart"></span></a>
+						<a class="btn btn-default" ng-click="toggleModal($index)"><span class="glyphicon glyphicon-plus"></span></a>
+					</div>
+				</div>
+			</li>
+		</ul>
+	</accordion-group>
+</accordion>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/visites.html	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,34 @@
+<accordion close-others="false">
+	<accordion-group ng-repeat="parentBook in books | filter:{ parent_visit: 'null', idArticle: '!null' } | orderBy: 'date' " is-open=true>
+
+		<accordion-heading>
+			<a class="title" ng-click="$event.stopPropagation();" href="#/visites/{{ parentBook.id }}">{{ parentBook.title }}</a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation();"><span class="glyphicon glyphicon-share"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); edit()"><span class="glyphicon glyphicon-cog"></span></a>
+			<a class="pull-right" ng-click="$event.stopPropagation();" href="#/slideshow/{{ parentBook.id }}"><span class="glyphicon glyphicon-eye-open"></span></a>
+			<a class="pull-right" ng-click="$event.preventDefault(); $event.stopPropagation(); addBook(parentBook.id)">Créer un Book</a>
+        </accordion-heading>
+
+        <a class="nbrObjects">{{parentBook.slides.length}} objets</a>
+
+        <ul ng:model="slides" class="list-unstyled list-inline gallery container">
+				  <li class="col-md-2 item" ng-repeat="i in parentBook.slides | limitTo : 5"> 
+				    <div class="img-ctn">
+				        <img class="img img-responsive image" ng-src="{{ i.details.images[0] }}"/>
+				        <p>{{ i.details.title }}</p>
+				        <div class="gallery-buttons">
+				         
+				          <a class="btn btn-default" ng-click=""><span class="glyphicon glyphicon-heart"></span></a>
+				          <a class="btn btn-default" ng-click="toggleModal($index)"><span class="glyphicon glyphicon-plus"></span></a>
+				         
+				        </div>
+				    </div>
+				  </li>
+			</ul>
+
+	  
+	</accordion-group>
+	
+</accordion>
+
+<a class="btn btn-default" ng-click="addBook()"><span class="glyphicon glyphicon-plus"></span></a>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/visites_controller.js	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,146 @@
+(function(){
+	'use strict';
+
+	angular.module('ammicoVisites',['ngRoute', 'ui.sortable'])
+	.controller('visitesCtrl', function($scope, $location, $modal, ammicoApi){
+
+		//get list book
+		$scope.books = ammicoApi.listBooks.query({format:'json'}, function(data){
+			data.sort(function (a, b) {
+				return a.date < b.date;
+			});
+
+			for (var i = 0; i < data.length; i++) {
+		    	if (data[i].idArticle){
+		    		data[i].slides = ammicoApi.booksSlides.query({idBook:data[i].id, format:'json'});
+		    	}
+			}	
+		});
+
+		$scope.toggleModal = function (index) {
+
+			var modalInstance = $modal.open({
+				templateUrl: 'visites/add_book_modal.html',
+				controller: 'ModalAddVisitesCtrl',
+				size: 'sm'
+			});
+
+			modalInstance.result.then(function (idBook) {
+				var newSlide = {
+					book: idBook,
+					idInventory: $scope.results.hits[index].metas_dict.inventorynumber
+				};
+				ammicoApi.listSlides.save(newSlide);
+			});
+		};
+
+
+		$scope.addBook = function (idParent) {
+			$modal.open({
+				templateUrl: 'visites/add_modal_visites.html',
+				controller: 'ModalAddVisitesCtrl'
+			}).result.then(function (title) {
+				//add book with the title written in the modal
+				ammicoApi.listBooks.save({idParent:idParent, title: title}, function(newBook){
+					$scope.books.push(newBook);
+				});
+			});
+		};
+		
+	})
+
+
+  .controller('visiteCtrl', function($scope, ammicoApi, $routeParams, $modal) {
+		//get the slides of a book
+		$scope.slides = ammicoApi.booksSlides.query({idBook:$routeParams.idVisit, format:'json'}, function(data){
+			data.sort(function (a, b) {
+				return a.orderIndex > b.orderIndex;
+			});
+			
+		});
+
+
+		$scope.toggleModal = function (index) {
+
+			var modalInstance = $modal.open({
+				templateUrl: 'visites/add_book_modal.html',
+				controller: 'ModalAddVisitesCtrl',
+				size: 'sm'
+			});
+
+			modalInstance.result.then(function (idBook) {
+				var newSlide = {
+					book: idBook,
+					idInventory: $scope.results.hits[index].metas_dict.inventorynumber
+				};
+				ammicoApi.listSlides.save(newSlide);
+			});
+		};
+
+		$scope.addBook = function (idParent) {
+			$modal.open({
+				templateUrl: 'visites/add_modal_visites.html',
+				controller: 'ModalAddVisitesCtrl'
+			}).result.then(function (title) {
+				//add book with the title written in the modal
+				ammicoApi.listBooks.save({idParent:idParent, title: title}, function(newBook){
+					$scope.books.push(newBook);
+				});
+			});
+		};
+		
+		$scope.sortableOptions = {
+				stop: function() {
+					var order = $scope.slides.map(function(i){
+						return i.id;
+					});
+					ammicoApi.order.save({idBook:$routeParams.idVisit}, {order: order});
+				}
+		};
+
+
+
+		$scope.deleteItem = function(i){
+			if(0<=i && i<$scope.slides.length){
+				if(window.confirm('Êtes-vous sûr(e) de vouloir effacer cet élément ? Cette action est irrémédiable.')){
+					//delete a slide
+					ammicoApi.slide.delete({idSlide: $scope.slides[i].id}, function(){
+						$scope.slides.splice(i, 1);
+					},
+					function(error) {
+						if (error.status === 404){
+							$scope.slides.splice(i, 1);
+						}
+					});
+				}
+			}
+		};
+
+	})
+
+
+	.controller('ModalAddVisitesCtrl', function($scope, ammicoApi, $modalInstance) {
+
+		$scope.add = function(){
+			$modalInstance.close($scope.title);
+//			ammicoApi.listBooks.save({title: $scope.title}, function(newBook){
+//			});
+		};
+		$scope.cancel = function () {
+			$modalInstance.dismiss('cancel');
+		};
+
+		$scope.books = ammicoApi.listBooks.query({format:'json'});
+		
+		$scope.addToBook = function(idBook){
+			$modalInstance.close(idBook);
+		};
+
+		$scope.cancel = function () {
+			$modalInstance.dismiss('cancel');
+		};
+
+	
+	});
+
+})();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/app/visites/visites_controller_test.js	Fri May 22 12:47:16 2015 +0200
@@ -0,0 +1,8 @@
+'use strict';
+
+describe("visites_controller_test", function(){
+    it("should assert something",function(){
+        expect(true).toBe(true);
+  
+	})
+})
\ No newline at end of file
--- a/client/gulpfile.js	Fri May 22 12:37:37 2015 +0200
+++ b/client/gulpfile.js	Fri May 22 12:47:16 2015 +0200
@@ -96,7 +96,7 @@
 
 gulp.task('copy-index', function() {
     gulp.src('./app/index.html')
-        .pipe(gulp.dest('./build'));
+        .pipe(gulp.dest(buildFolder));
 });
 
 gulp.task('copy-data', function() {