[ Application 58] « Scanne ton Employé » Journal de développement au jour 2

scanneIntroduction JOUR 2


Aujourd’hui, je me concentre sur la validation du formulaire et la génération de la carte plastique avec le code barre.

A ce stade, on peut taper les données d’un utilisateur, puis cliquer sur le boutton « Générer la carte » pour générer la carte et le code barre de l’employé, on génére aussi l’identifiant.

Si on imprime avec une imprimante ce code barre puis qu’on le scanne avec le scanner USB, alors, on récupère l’identifiant de l’employé !

Tout cela se passe uniquement dans la vue nouveau.html et dans le controleur ‘nouveauCtrl’

J’ai fait tout ça en 3h30 à peu près.

Pour tester l’état de l’application au jour 2, cliquer ici .

Explication Technique :


  • Compatibilité : Chrome, Opéra, non compatible avec Firefox(pour l’instant, à cause de l’input Date et de la validation formulaire)
  • Pour générer un code barre en fonction d’une variable, j’utilise la directive suivante AngularJs 1.5 : https://github.com/zhuk-aa/angular-barcode-generator.
  • La variable générant le code barre est la concaténation de la première lettre du prénom et du nom, ainsi que la date de naissance de la personne, cela crée un ID qui sera utilisé pour identifier les personnes, dans le programme, et lors d’un scan laser.
  • La validation des champs utilise la validation interne du navigateur et en même temps la validation optionnelle de AngularJs, qui se vérifie lorsque myForm.$valid est true, en fait, je me sers de cette validation pour valider les données pour la génération de la carte ET pour valider l’enregistrement en base de données du nouvel employé. AngularJs 1.5 permet de vérifier la longueur d’une variable entrée par exemple et bien plus.
  • Pour rappel, toutes les variables du formulaire sont contenues dans un objet JSON qui se modifie en temps réel, il s’appelle $scope.nouvelEmploye , du coup, si je mets à jours le nom du nouvel employé dans le formulaire, alors la variable $scope.nouvelEmploye.nom sera peuplée.
  • Un autocomplete GoogleMap remplit automatiquement la case adresse, façon noSql-bigData

PROBLEME PROVISOIRE AVEC L’IDENTIFIANT D’UN EMPLOYE:

La contrainte d’intégrité et d’unicité de l’identifiant d’un employé n’est pas respectée au jour 2.

Autrement dit, le système de concaténation de la première lettre du prénom, du nom et de la date de naissance n’est pas suffisant, parce que, dans le cas ou il y a ait 100 000 employés, il est probable qu’il y aura des doublons.

Mais pour l’instant, j’ai du faire comme cela, parce que sinon, si l’identifiant est trop grand, le code barre généré dépasse le format de la carte !

Il faudra donc revenir sur ce système… De toute façon on peut tout placer dans le code barre, même un identifiant auto-incrémental généré par Mysql, on fait ce que l’on veut dans la mesure ou la contrainte d’unicité et d’intégrité soit respectée, hi hi !

Photo de l’application:


app

Le code :


INDEX.HTML n’a pas changé hormis les liens vers les nouvelles librairies, que j’ai téléchargé avec Bower comme d’hab, c’est hyper facile.

On voit que j’ai ajouté ma directive qui génére les codes barres, et l’api google map, avec l’autocomplete qui peut se mettre sur tous les champs input html(ça déchire !)

J’ai aussi placé les directives dans un autre fichier.

:


<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Neutre</title>
	<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">

		<!-- CHARGEMENT DES LIBRAIRIES -->

		<!-- JQUERY ET BOOTSRAP -->
		<script src="bower_components/jquery/dist/jquery.min.js"></script>
		<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
		<link rel="stylesheet" type="text/css" href="bower_components/bootstrap/dist/css/bootstrap.min.css">

		<!-- ANGULARJS -->
		<script src='bower_components/angular/angular.min.js'></script>
		<script src="bower_components/angular-route/angular-route.min.js"></script>
		<script src="bower_components/angular-locale_fr-fr/angular-locale_fr-fr.js"></script>
		<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.js"></script>

		<!-- DIRECTIVE GENERATRICE DE CODE BARRES -->
		<link rel="stylesheet" href="bower_components/barcodeGenerator/barcode.css" type="text/css"/>
		<script type="text/javascript" src="bower_components/barcodeGenerator/barcodeGenerator.js"></script>	

		<!-- GOOGLE MAP ET AUTOCOMPLETE GOOGLE -->
		<script src="https://maps.googleapis.com/maps/api/js?libraries=places"></script>
		<script src="bower_components/angular-google-places-autocomplete/src/autocomplete.js"></script>
		<link rel="stylesheet" href="bower_components/angular-google-places-autocomplete/src/autocomplete.css">

		<!-- APPLICATION PERSO -->
		<script src="js/app.js"></script>  <!-- Chargement des modules AngularJs et des controleurs -->
		<script src="js/directives.js"></script>  <!-- Chargement des directives et des filtres -->
		<link rel="stylesheet" type="text/css" href="css/style.css"><!-- // Les css de notre app -->

		<!-- FIN DE CHARGEMENT DES LIBRAIRIES -->
</head>

<body ng-app="neutre" >

<!--  MENU -->
       <nav class="navbar navbar-default" >
		  <div class="container-fluid">
			<!-- Grouping pour meilleur affichage mobile -->
			<div class="navbar-header">
			  <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
				<span class="sr-only">Activer la navigation</span>
				<span class="icon-bar"></span>
				<span class="icon-bar"></span>
				<span class="icon-bar"></span>
			  </button>
			  <a class="navbar-brand" href="#"><img src="img-app/scanne.jpg" style="width:130px;height:70px;"></img></a>
			</div>

			<!-- Collecte les liens pour que lors de l utilisation sur un mobile, cela se contracte bien -->
			<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
			  <ul class="nav navbar-nav" bs-active-link>
			  <li class="active"><a href="#/accueil"><span class="glyphicon glyphicon-home" aria-hidden="true"></span></i>  Accueil <span class="sr-only">(current)</span></a></li>
				<li ><a href="#/nouveau"><span class="glyphicon glyphicon-user" aria-hidden="true"></span></i>  Nouveau <span class="sr-only">(current)</span></a></li>
				<li><a href="#/liste"><span class="  glyphicon glyphicon-barcode" aria-hidden="true"></span> Liste</a></li>
				<li class="dropdown">
				  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class=" glyphicon  glyphicon-scale" aria-hidden="true"></span> Paramêtres<span class="caret"></span></a>
				  <ul class="dropdown-menu">

					<li><a href="#">Paramétrer le scanner</a></li>
					<li><a href="#">Paramétrer la page d'accueil</a></li>

					<li role="separator" class="divider"></li>
					<li><a href="#">Gérer les catégories d'employés</a></li>
					<li><a href="#">Gérer les horaires</a></li>
				  </ul>
				</li>
				<li class="dropdown">
				  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon  glyphicon-log-in" aria-hidden="true"></span>  Identification<span class="caret"></span></a>
				  <ul class="dropdown-menu">
					<li><a href="#">Mon compte</a></li>
					<li role="separator" class="divider"></li>
					<li><a href="#">Sortir</a></li>
				  </ul>
				</li>
			  </ul>

			  <ul class="nav navbar-nav navbar-right">
			  <form class="navbar-form navbar-right" role="search">
				<div class="form-group">
				  <input type="text" class="form-control" placeholder="Rechercher">
				</div>
				<button type="submit" class="btn btn-default">Soumettre</button>
			  </form>
				<!-- <li><a href="#">Link</a></li> -->

			  </ul>
			</div><!-- /.navbar-collapse -->
		  </div><!-- /.container-fluid -->
		</nav>

	<!-- <ol class="breadcrumb">
	  <li><a href="#/accueil">Accueil</a></li>
	  <li><a href="#/nouveau">Nouveau</a></li>
	  <li> <a href="#/scanner">Scanner</a></li>
	</ol> -->

<!-- Cette balise NG-View va afficher les différentes vues -->
<div ng-view></div>						

</body>
</html>

La vue nouveau.html est celle ou j’ai opéré aujourdhui , on peut voir le paramétrage de contrôle des entrées, et les boutons qui lancent des fonctions différentes.

<div class="row ">
	<div class="col-lg-12 " >
		 <div class="panel panel-warning">

			<!-- EN TETE DU PANEL -->
			<div class="panel-heading">
				<span class="glyphicon glyphicon glyphicon-user"  aria-hidden="true"></span> Nouveau
			</div>
			<form name="myForm"  >
			<!-- CORPS DU PANEL -->
			<div class="panel-body " style="min-height:600px;" >

				<div class="col-lg-12" >
					<div class="form-group input-group">
					  <span class="input-group-addon">Image</span>
						  <img src = "{{nouvelEmploye.image}}" class = "img-responsive" style ="width : 100px; height:100px;">
					</div>
				</div >
				<div class="col-lg-6" >

						<div class="form-group input-group">
							<span class="input-group-addon" >Nom</span>
							<input name="nom" type="text" class="form-control text " ng-model = "nouvelEmploye.nom" ng-minlength="1" ng-maxlength="20" required /></input>
							<div ng-messages="myForm.nom.$error" role="alert"  ng-if="myForm.$submitted" style="color:red">
								<div ng-message="required" >Entrez une valeur.</div>
								<div ng-message="minlength">Pas assez long.</div>
								<div ng-message="maxlength">Trop long.</div>
							  </div>
						</div>
						<div class="form-group input-group">
							<span class="input-group-addon" >Prénom</span>
							<input name="prenom" type="text" class="form-control text " ng-model = "nouvelEmploye.prenom" ng-minlength="1" ng-maxlength="20" required /></input>
							<div ng-messages="myForm.prenom.$error" role="alert"  ng-if="myForm.$submitted" style="color:red">
								<div ng-message="required" >Entrez une valeur.</div>
								<div ng-message="minlength">Pas assez long.</div>
								<div ng-message="maxlength">Trop long.</div>
							 </div>
						</div>
						<div class="form-group input-group">
							<span class="input-group-addon">Date Naissance</span>
							<input type="date" class="form-control text " ng-model = "nouvelEmploye.dateNaissance" required /></input>
						</div>

				</div>

				<div class="col-lg-6" >
					<div class="form-group input-group">
						<span class="input-group-addon">Adresse</span>
						<input type="text" class="form-control text " g-places-autocomplete ng-model = "nouvelEmploye.adresse" ng-minlength="2" ng-maxlength="200" required /></input>
					</div>
					<div class="form-group input-group">
						<span class="input-group-addon">Email</span>
						<input name="email" type="email" class="form-control text " ng-model = "nouvelEmploye.email" ng-minlength="1" ng-maxlength="45" required /></input>
						<div ng-messages="myForm.email.$error" role="alert"  ng-if="myForm.$submitted" style="color:red">
							<div ng-message="required" >Entrez une valeur.</div>
							<div ng-message="minlength">Pas assez long.</div>
							<div ng-message="maxlength">Trop long.</div>
						 </div>
					</div>

					<div class="form-group input-group" ng-show="nouvelEmploye.identifiant">
						<span class="input-group-addon">Identifiant </span>
						<input type="text" class="form-control text " ng-model = "nouvelEmploye.identifiant" disabled /></input>
					</div>
				</div>

				<div class="col-lg-12" >
					<div class="panel well">
						<span class="glyphicon glyphicon-credit-card"  aria-hidden="true"></span> Carte identifiante avec Code Barre

						<!-- GENERATION DE LA CARTE -->
						<div class="card">
							<div class="card-body">
								<div barcode-generator="{{generationCodeBarre}}" style="height:85px;"></div>
								<h4 style="color:black;">{{nouvelEmploye.nom | capitalize}} {{nouvelEmploye.prenom | capitalize}}</h4>
							</div>
						</div>

					</div>
				</div>

			</div>

			<!-- PIED DE PAGE DU PANEL -->
			<div class="panel-footer text-right">
				<div class="btn-group" role="group" aria-label="...">
				<button class="btn btn-default">
					<span class="glyphicon  glyphicon-print"  aria-hidden="true"></span>
					imprimer la carte

				</button >
				<button ng-click="myForm.$valid && genererCarte()" class="btn btn-default">
					<span class="glyphicon  glyphicon-credit-card"  aria-hidden="true"></span>
					Générer la carte

				</button >
					<button ng-click="myForm.$valid && sauvegarderUtilisateur()" class="btn btn-default">
					<span class="glyphicon  glyphicon-ok"  aria-hidden="true"></span>
					Sauvegarder

				</button>
				</div>

				</form>

			</div>

		 </div>
	</div>
</div> 

Et enfin le controleur nouveauCtrl, qui pilote la vue nouveau.html, on voit que je crée le nouvel objet nouvelEmploye, puis on voit que j’ai 2 fonctions, une qui génère la carte et le code barre($scope.genererCarte()), et une qui va enregistrer l’objet JSON $scope.nouvelEmploye en noSql dans Firebase(ou java ou php avec sql), la fonction s’appelle $scope.sauvegarderUtilisateur ():


angular.module('neutre', ['ngRoute','ngMessages','barcodeGenerator','google.places'])
/*
ROUTING DE VUES */
.config(function ($routeProvider, $locationProvider){
  $routeProvider
	.when('/accueil', {
	  templateUrl: 'vues/accueil.html',
	  controller: 'accueilCtrl'
	})
	.when('/nouveau', {
	  templateUrl: 'vues/nouveau.html',
	  controller: 'nouveauCtrl'
	})
	.when('/liste', {
	  templateUrl: 'vues/liste.html',
	  controller: 'listeCtrl'
	})
	.when('/parametres', {
	  templateUrl: 'vues/parametres.html',
	  controller: 'paramsCtrl'
	})
	.otherwise({redirectTo: '/accueil'});
})

/* CONTROLEUR DE LA VUE ACCUEIL */
.controller('neutreCtrl', function($scope) {
/* FIN DU CONTROLEUR */
})

/* CONTROLEUR DE LA VUE NOUVEAU */
.controller('nouveauCtrl', function($scope) {
	/* INITIALISATION DES VARIABLES ET OBJETS :	 */
	$scope.nouvelEmploye		={};/*  L'objet contiendra toutes  les variables forumlaire du nouvel employé */
	$scope.nouvelEmploye.image	="img-app/employe.jpg";/*  Tant qu on a pas uploade une image, cest celle ci qui s affiche */
	$scope.generationCodeBarre=""

	$scope.genererCarte = function(){
		console.log($scope.nouvelEmploye);
		/* FORMATAGE DU CODE BARRE , CA NOUS DONNE UN TRUC COMME CA : ALBERT DUPONT NE LE 03/02/1956 NOUS DONNE AU FORMAT CODEBAR AD03021956 CEST SON IDENTIFIANT*/
		var prefixe 		= $scope.nouvelEmploye.prenom.substring(0,1);
		var nom 			= $scope.nouvelEmploye.nom.substring(0,1);;

		var jour =  $scope.nouvelEmploye.dateNaissance.getUTCDate();
		var mois =  $scope.nouvelEmploye.dateNaissance.getUTCMonth() + 1; //months from 1-12
		var annee =  $scope.nouvelEmploye.dateNaissance.getUTCFullYear();
		if(jour<10)  { jour='0'+jour };
		if(mois<10)  { mois='0'+mois };

		$scope.generationCodeBarre			=	prefixe+nom+jour+mois+annee;
		$scope.nouvelEmploye.identifiant 	=  	prefixe+nom+jour+mois+annee;
	};

	$scope.sauvegarderUtilisateur = function(){
		alert('La sauvegarde sur Firebase cest pour demain  !');
	};

/* FIN DU CONTROLEUR */
})

Publicités