[AngularJs] Calculer la moyenne des valeurs d’une colonne de table HTML, avec une seule fonction générique

Introduction

Une fonction qui prends en paramêtre le modèle de données de la table, et le nom de la colonne dont on veut calculer la moyenne .

 

Code




<table class="table table-striped table-bordered table-hover">
   <tr>
   <thead>
      <th>
         
         Période
      </th>
      <th title="Nombre de jours travaillés dans le mois">Nbre de JT </th>
      <th title="Nombre d'appels par jours">
         
         Nb Appels
      </th>
      <th title="Nombre d'appels par jours">
         
         Nbre d'appels/jour
      </th>
      <th title="Nombre de fiches traitées">
         
         Nbre fichestraitées
      </th>
      <th>
         
         Heures Tr 
      </th>
      <th>
         
         Appels/heure
      </th>
      <th>
         
         Tx de rotation
      </th>
      <th>
         
         Nbre contacts PDG
      </th>
      <th>
         
         Nbre contact / JT
      </th>
      <th>
         
         Tx contact
      </th>
      <th>
         
         Nbre de devis créés
      </th>
      <th>
         
         Tx d'accroche devis
      </th>
      <th>
         
         Tx d'efficacité de vente
      </th>
      <th>
         
         Tx efficacité entrant
      </th>
      <th>
         
         Tx efficacité sortant
      </th>
      <th>
         
         Nb de ventes
      </th>
      <th>
         
         Nb Ventes  entrantes
      </th>
      <th>
         
         Nb Ventes sortantes
      </th>
      <!-- <th>Ventes opé</th>	 -->
   </thead>
   <thead>
      <th>
         
         <i class="fa fa-calendar  bg-secondary p-2 font-xl mr-3  ">
      </th>
      <th>
         
         <i class="fa fa-industry  bg-primary p-2 font-xl mr-3 pull-center "> </i>
      </th>
      <th title="Nombre d'appels par jours">
         
         <i class="fa fa-phone  bg-primary p-2 font-xl mr-3 pull-center "> </i>
      </th>
      <th title="Nombre d'appels par jours">
         
         <i class="fa fa-phone  bg-secondary p-2 font-xl mr-3 pull-center "></i>
      </th>
      <th title="Nombre de fiches traitées">
         
         <i class="fa fa-map-o  bg-primary p-2 font-xl mr-3 pull-center "></i>
      </th>
      <th>
         
         <i class="fa fa-industry  bg-primary p-2 font-xl mr-3 pull-center "></i>
      </th>
      <th>
         
         <i class="fa fa-repeat  bg-warning p-2 font-xl mr-3 pull-center "></i>
      </th>
      <th>
         
         <i class="fa fa-eur  bg-secondary p-2 font-xl mr-3  ">
      </th>
      <th>
         
         <i class="fa fa-user-plus  bg-danger p-2 font-xl mr-3 "></i>
      </th>
      <th>
         
         <i class="fa fa-user-plus  bg-secondary p-2 font-xl mr-3 "></i>
      </th>
      <th>
         
         <i class="fa fa-user-plus  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-file-o  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-file-o  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-thumbs-o-up  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-thumbs-o-up  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-thumbs-o-up  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-eur  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-eur  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <th>
         
         <i class="fa fa-eur  bg-secondary p-2 font-xl mr-3  "></i>
      </th>
      <!-- <th>Ventes opé</th>	 -->
   </thead>
   </tr>
   <tr>
      <td> {{::s.nom}}</td>
      <td> {{::s.nb_j_travailles}}</td>
      <td> {{::s.nb_appels}}</td>
      <td> {{(s.nb_appels / s.nb_j_travailles) | number: 2}}</td>
      <td> {{::s.nbfiches_creees}}</td>
      <td> {{::s.heures_mensuelle}}</td>
      <td> {{(s.nb_appels / s[$index].travail_mois) | number: 2 }}</td>
      <td> {{}}</td>
      <td> {{::s.nb_contacts}}</td>
      <td> {{}}</td>
      <td> {{}}</td>
      <td> {{::s.nbdevis_crees}}</td>
      <td> {{(s.nbdevis_crees/s.nb_argus) | number: 2}}</td>
      <td> {{::s.tx_efficacitevente}}</td>
      <td> {{::s.tx_efficaciteventeentrant}}</td>
      <td> {{::s.tx_efficaciteventesortant}}</td>
      <td> {{::s.nb_vente}}</td>
      <td> {{::s.nb_venteentrant}}</td>
      <td> {{::s.nb_ventesortant}}</td>
      <!-- <td> {{}}</td> -->
   </tr>
   <tr>
      <td>Moyenne</td>
      <td>{{ctrl.calculer_moyenne(ctrl.sc,'nb_j_travailles')}}</td>
      <td>{{ctrl.calculer_moyenne(ctrl.sc,'nb_appels')}}</td>
      <td></td>
      <td>{{ctrl.calculer_moyenne(ctrl.sc,'nbfiches_creees')}}</td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
   </tr>
   <tr>
      <td>Total</td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
      <td></td>
   </tr>
</table>


La fonction :

this.calculer_moyenne = function(modele, champs) {

    if (modele) {
        var sum = 0;
        for (var i = 0; i < modele.length; i++) {

            if (modele[i][champs]) {
                sum += parseInt(modele[i][champs], 12); //don't forget to add the base 
            }
        }

        var avg = sum / modele.length;

        return (avg).toFixed(2);
    }

}
Publicités

[AngularJs 1.6.2] Communiquer des variables à des components

Introduction

On a 20 graphiques à réaliser, tous avec la même emprunte pattern de modèle de données , on va forcément éviter de créer 20 controllers pour gérer tout ça .
On tente donc de créer un component angularJS qui permet de simplifier tout cela , car on peut lui passer des variables.

Note : La v 1.7 de AngularJs gère le transfert de datas aux components un peu différement.

Lien :

https://stackoverflow.com/questions/53170065/angularjs-template-component-not-rendering-variables

[Sql] Imbriquer des requêtes pour réduire la taille du back end .

Introduction
Avec postgreSQl, il faut dès que possible imbriquer les requêtes SQL, pour aller plus vite et réduire la taille du back end

Code exemple qui calcule nbVente et nbDevis, puis permet de faire des calculs dans le select initial (calcul non présent):

SELECT nbVentes.nb_vente_entrant,nbDevis.nb_devis FROM 
(
SELECT 
 COUNT(v.prix_vente) AS nb_vente_entrant 
 FROM crm_vente AS v
 LEFT JOIN crm_devis AS d ON v.id_crm_devis = d.id_crm_devis
 WHERE 1=1 
 AND d.type_vente = 'Entrant'
 AND date_part('year', v.date_vente) = 2018
 ) AS nbVentes
,
 (
SELECT 
 COUNT(*) AS nb_devis
 FROM crm_devis AS c 
 WHERE 1=1 
 AND date_part('year', c.date_creation) = 2018
 ) AS nbDevis

La requête peut devenir grosse , mais reste cool à gérer, et surtout ça remplit tout le front end d’un seul coup, car après on encode tout ça en JSON : exemple !

SELECT c.numero,c.nom,R.*,K.nb_j_travailles,Z.nbfiches_creees,D.nbdevis_crees,A.nb_argus FROM commerce_mois AS c

LEFT OUTER JOIN

(
	SELECT s.txn_month,s.nb_j_travailles

	   FROM ( SELECT count(distinct(date_trunc('day',calldate))) AS nb_j_travailles,
	   date_part('month'::text,h.calldate) AS txn_month,
	   date_part('year'::text,h.calldate) AS txn_year
			   FROM crm_historique AS H
				WHERE date_part('year'::text,h.calldate) = 2018
				GROUP BY date_part('month'::text, h.calldate), date_part('year'::text,h.calldate)
			 ) s

	  GROUP BY  s.txn_month,s.nb_j_travailles
	  ORDER BY  s.txn_month
  ) K

  ON c.numero = K.txn_month
  

LEFT OUTER JOIN

(
	SELECT s.txn_month,s.nb_appels

	   FROM ( SELECT count(h.calldate) AS nb_appels,
	   date_part('month'::text,h.calldate) AS txn_month,
	   date_part('year'::text,h.calldate) AS txn_year
			   FROM historique AS H
			   WHERE date_part('year'::text,h.calldate) = 2018
				GROUP BY date_part('month'::text, h.calldate), date_part('year'::text,h.calldate)
			 ) s

	  GROUP BY  s.txn_month,s.nb_appels
	  ORDER BY  s.txn_month
  ) R

  ON c.numero = R.txn_month

LEFT OUTER JOIN

(

SELECT s.txn_month,s.nbfiches_creees

   FROM ( SELECT count(c.date_contact_pdg) AS nbfiches_creees,
   date_part('month'::text,c.date_contact_pdg) AS txn_month,
   date_part('year'::text,c.date_contact_pdg) AS txn_year
		   FROM comptes AS C
		   WHERE date_part('year'::text,c.date_contact_pdg) = 2018
			GROUP BY date_part('month'::text,c.date_contact_pdg), date_part('year'::text,c.date_contact_pdg)
		 ) s

  GROUP BY  s.txn_month,s.nbfiches_creees
  ORDER BY  s.txn_month
 ) Z

 ON c.numero = Z.txn_month

 LEFT OUTER JOIN

(

SELECT s.txn_month,s.nbdevis_crees

   FROM ( SELECT count(c.date_creation) AS nbdevis_crees,
   date_part('month'::text,c.date_creation) AS txn_month,
   date_part('year'::text,c.date_creation) AS txn_year
		   FROM devis AS C
		   WHERE date_part('year'::text,c.date_creation) = 2018
			GROUP BY date_part('month'::text,c.date_creation), date_part('year'::text,c.date_creation)
		 ) s

  GROUP BY  s.txn_month,s.nbdevis_crees
  ORDER BY  s.txn_month
 ) D

 ON c.numero = D.txn_month


LEFT OUTER JOIN

(

SELECT s.txn_month,s.nb_argus

   FROM ( SELECT count(c.date_creation) AS nb_argus,
   date_part('month'::text,c.date_creation) AS txn_month,
   date_part('year'::text,c.date_creation) AS txn_year
		   FROM crm_devis AS C
		    inner join comptes  AS cc ON C.id_comptes = cc.id_crm_comptes
			WHERE cc.contact_pdg LIKE 'Oui'
		   AND date_part('year'::text,c.date_creation) = 2018
			GROUP BY date_part('month'::text,c.date_creation), date_part('year'::text,c.date_creation)
		 ) s

  GROUP BY  s.txn_month,nb_argus
  ORDER BY  s.txn_month
 ) A

 ON c.numero = A.txn_month

[AngularJs + PHP] Un infinite Scroll sur une table HTML

Introduction :
Un infinite scroll permet à l’utilisateur d’avoir la sensation de lire toutes les données d’une table même si il y en a des milliers, sans faire défaillir le front end .

Fonctionnement :
On charge les enregsitrements (row) 20 par 20 .
Au début on est à 0, puis, JQUERY détecte lorsque l’on atteint la fin de la div (bottom), il relance alors à chaque fois la requete SQL dans le Back End, tout en renvoyant le dernier ID acquis, afin de pouvoir faire un +20 . La lecture de la table devient très smooth et super rapide, la vue en elle même se charge instantanément ! on push à chaque fois les 20 enregistrements suivants dans le modèle de données, qui s’affiche alors dans la table HTML.

infintescroll.png

Lire la suite

[AngularJs] Communiquer avec un ng-repeat parent ( nested ng-repeats)

Introduction

On peut intéragir avec l’objet du ng-repeat parent, en modifiant des choses dans le ng-repeat enfant .
Attention, avec Chrome, il faut utiliser ng-change() dans les select , et pas de ng-click.

Exemple des filtres:
ON récupère le $index du parent avec outerIndex
Ainsi on peut ensuite modifier des variables dans le parent, de par la fonction de l’enfant ng-change().
element est un objet parent provoqué par le ng -repeat et contient des selects aux objets uniques.

Astuce : si on enregsitre tout le modèle de données JSON dans un champs de bdd avec Serialize, ensuite, on retrouve tout tout de suite, tout simplement en désarialisant l’objet puis en l’affectant à la variable JS, et cela en quelques instants un peu comme en big data .
 

		<li class="list-group-item" ng-repeat="element in $ctrl.filtres" ng-init="outerIndex=$index"> 
			<b>Mon critère numéro {{$index}} :</b><br>
					
			<select ng-options="champs.column_name as champs for champs in $ctrl.table  " 
				ng-model="element.champs"  ng-change="$ctrl.verify_data_type(outerIndex,element.champs)" ng-init="innerIndex=$index"> -->
			 <option value=""> </option>
			 </select> 
			
			 <select ng-model="element.champs"  ng-change="$ctrl.verify_data_type(outerIndex,element.champs)" ng-init="innerIndex=$index" class="form-control" >  
				<option value="">Champs</option> 
				 <option  ng-repeat ="champs in $ctrl.table"   value="{{champs.column_name}}" >{{champs.column_name}}</option> 
			 </select> 
			
			
			
			
			<select ng-model="element.operateur" class="form-control"  >
				<option value="">Opérateur</option>
				<option ng-repeat ="operateur in $ctrl.operateurs" value="{{operateur.nom}}" >{{operateur.traduction}}</option>
			</select>
			
			<input ng-if="element.showText" 	ng-model="element.critere" 		type ="text"  	class="form-control" placeholder="Votre recherche" 		title="Entrez plusieurs critères avec des virgules" required></input>
			<input ng-if="element.showDate" 	ng-model="element.critere" 		type ="date"  	class="form-control" placeholder="Une date" 			required></input>
			<input ng-if="element.showInteger " ng-model="element.critere" 		type ="number"  class="form-control" placeholder="Un nombre" 			required></input>
		</li>

Un exemple de fonction qui agit sur le ng-repeat parent, grâce à $index : outerIndex, c’est compatible avec CHROME :

     this.verify_data_type = function(outerIndex,champs){
            
			 console.log(outerIndex);
			 
			 console.log(champs);
			 
			
			
            switch(champs.data_type) {
                case 'integer':
                    this.filtres[outerIndex].showInteger = true;
                    this.filtres[outerIndex].showDate = false;
                    this.filtres[outerIndex].showText = false;
                    break;
                case 'date':
                    this.filtres[outerIndex].showInteger = false;
                    this.filtres[outerIndex].showDate = true;
                    this.filtres[outerIndex].showText = false;
                    break;
                case 'character varying':
                    this.filtres[outerIndex].showInteger = false;
                    this.filtres[outerIndex].showDate = false;
                    this.filtres[outerIndex].showText = true;
                    break;
                default:
                    this.filtres[outerIndex].showInteger = false;
                    this.filtres[outerIndex].showDate = false;
                    this.filtres[outerIndex].showText = true;
            } 
		}

[PHP] Créer un objet à partir de plusieurs résultats SQL, puis envoyer ça au front end

Intro :

On peut envoyer soit un array, soit un objet, ici c’est un objet :

Code exemple :

Le web service :


function GetActivite() {
	$filtres 		= json_decode(file_get_contents("php://input")); 
	$suiviPersonnel = new SuiviPersonnel();
	$result		 	= $suiviPersonnel->GetActivite($filtres);
	if($result){
		echo(json_encode($result));  
	}
}

La méthode qui retourne un objet à partir de résultats SQL



/**
 * Fenetre Activité de la vue suivi_activite
 * @param $filtres => mois | annee| id_user
 * @return array | false
 */
public function GetActivite($filtres)
	{
	try
		{
		$total = new stdClass(); // Cet objet va contenir tous les resultats puis on l'envoit à la fin au front end angularjs

		// $total->property = 'Here we go'; // Exemple d'injection de resultat dans l'objet ...
		// PHASE 1 : CALCUL DU TEMPS DAPPEL TOTAL

		$sql = "
                  SELECT
                  TO_CHAR((SUM(duration) || ' second')::interval, 'HH24:MI:SS') AS temps_appel
                  FROM " . self::TABLE . "
                  WHERE 1=1
                   ";
		if ($filtres->mois)
			{
			$sql.= " AND EXTRACT(MONTH FROM calldate) = " . $filtres->mois;
			}

		if ($filtres->annee)
			{
			$sql.= " AND EXTRACT(YEAR FROM calldate) = " . $filtres->annee;
			}

		if ($filtres->id_utilisateurs)
			{
			$sql.= " AND id_utilisateurs = " . $filtres->id_utilisateurs;
			}

		$req = $this->bdd->prepare($sql);
		$req->execute($tab_value);
		$result = $req->Fetch(PDO::FETCH_ASSOC);
		$req->closeCursor();
		$total->temps_appel = $result[temps_appel];

		// PHASE 2 : CALCUL DU NOMBRE APPEL MOYEN PAR HEURES

		$sql = "
                SELECT
              AVG(*) AS nombre_appels_moyen
              FROM " . self::TABLE . "
             WHERE 1=1
                ";
		if ($filtres->mois)
			{
			$sql.= " AND EXTRACT(MONTH FROM calldate) = " . $filtres->mois;
			}

		if ($filtres->annee)
			{
			$sql.= " AND EXTRACT(YEAR FROM calldate) = " . $filtres->annee;
			}

		if ($filtres->id_utilisateurs)
			{
			$sql.= " AND id_utilisateurs = " . $filtres->id_utilisateurs;
			}

		$req = $this->bdd->prepare($sql);
		$req->execute($tab_value);
		$result2 = $req->Fetch(PDO::FETCH_ASSOC);
		$req->closeCursor();
		$total->nombre_appels_moyen = $result2[nombre_appels_moyen];

		// PHASE 3 : CALCUL DU NOMBRE DE FICHES TRAITEES

		$sql = "
                SELECT
                COUNT(*) AS fiches_traitees
                FROM " . self::TABLE . "
                WHERE 1=1
                ";
		if ($filtres->mois)
			{
			$sql.= " AND EXTRACT(MONTH FROM calldate) = " . $filtres->mois;
			}

		if ($filtres->annee)
			{
			$sql.= " AND EXTRACT(YEAR FROM calldate) = " . $filtres->annee;
			}

		if ($filtres->id_utilisateurs)
			{
			$sql.= " AND id_utilisateurs = " . $filtres->id_utilisateurs;
			}

		$req = $this->bdd->prepare($sql);
		$req->execute($tab_value);
		$result3 = $req->Fetch(PDO::FETCH_ASSOC);
		$req->closeCursor();
		$total->fiches_traitees = $result3[fiches_traitees];

		// PHASE 4 : CALCUL DU NOMBRE DE CONTACTS

		$sql = "
                SELECT
                DISTINCT(COUNT('appeler')) AS nb_contacts
               FROM " . self::TABLE . "
               WHERE 1=1
                ";
		if ($filtres->mois)
			{
			$sql.= " AND EXTRACT(MONTH FROM calldate) = " . $filtres->mois;
			}

		if ($filtres->annee)
			{
			$sql.= " AND EXTRACT(YEAR FROM calldate) = " . $filtres->annee;
			}

		if ($filtres->id_utilisateurs)
			{
			$sql.= " AND id_utilisateurs = " . $filtres->id_utilisateurs;
			}

		$req = $this->bdd->prepare($sql);
		$req->execute($tab_value);
		$result4 = $req->Fetch(PDO::FETCH_ASSOC);
		$req->closeCursor();
		$total->nb_contacts = $result4[nb_contacts];

		// PHASE 5 : CALCUL DU NOMBRE APPEL TOTAL

		$sql = "
                SELECT
                 COUNT(*) AS nombre_appels
                 FROM " . self::TABLE . "
                WHERE 1=1
                ";
		if ($filtres->mois)
			{
			$sql.= " AND EXTRACT(MONTH FROM calldate) = " . $filtres->mois;
			}

		if ($filtres->annee)
			{
			$sql.= " AND EXTRACT(YEAR FROM calldate) = " . $filtres->annee;
			}

		if ($filtres->id_utilisateurs)
			{
			$sql.= " AND id_utilisateurs = " . $filtres->id_utilisateurs;
			}

		$req = $this->bdd->prepare($sql);
		$req->execute($tab_value);
		$result5 = $req->Fetch(PDO::FETCH_ASSOC);
		$req->closeCursor();
		$total->nombre_appels = $result5[nombre_appels];
		return $total;
		}

	catch(Exception $e)
		{
		die('Erreur : ' . $e->getMessage());
		}
	}


 

Puis, si on veut condenser les filtres dans une fonction :

	 public function GetActivite($filtres) {
        
		try {
			
			$total = new stdClass(); // Cet objet va contenir tous les resultats puis on l'envoit à la fin au front end angularjs
			// $total->property = 'Here we go'; // Exemple d'injection de resultat dans l'objet ...
			
			//  CALCUL DU TEMPS DAPPEL TOTAL 
			$sql  = "
				SELECT 
				TO_CHAR((SUM(duration) || ' second')::interval, 'HH24:MI:SS')  AS temps_appel 
				FROM " . self::TABLE . "
				WHERE 1=1 
			";
			
			$sql = $this->addFiltres($filtres,$sql);
			
			$req = $this->bdd->prepare($sql);
            $req->execute($tab_value);
            $result = $req->Fetch(PDO::FETCH_ASSOC);
            $req->closeCursor();
			
			$total->temps_appel = $result[temps_appel] ; 
			
			// CALCUL DU DUREE MOYENNE PAR APPEL
			 $sql  = "
				 SELECT 
				 ROUND(AVG(duration),2) AS duree_appel_moyen  
				 FROM " . self::TABLE . "
				 WHERE 1=1 
			 ";
			 $sql = $this->addFiltres($filtres,$sql);
			
			 $req = $this->bdd->prepare($sql);
             $req->execute($tab_value);
             $result = $req->Fetch(PDO::FETCH_ASSOC);
             $req->closeCursor();
			
			$total->duree_appel_moyen = $result[duree_appel_moyen]; 
			
			
			// CALCUL DU NOMBRE APPEL MOYEN PAR HEURES
			 $sql  = "
				 SELECT 
				 AVG(duration) AS nombre_appels_moyen_heure  
				 FROM " . self::TABLE . "
				 WHERE 1=1 
			 ";
			 $sql = $this->addFiltres($filtres,$sql);
			
			 $req = $this->bdd->prepare($sql);
             $req->execute($tab_value);
             $result = $req->Fetch(PDO::FETCH_ASSOC);
             $req->closeCursor();
			
			$total->nombre_appels_moyen_heure = $result[nombre_appels_moyen_heure]; 
			
			// CALCUL DU NOMBRE DE FICHES TRAITEES 
			$sql  = "
				SELECT 
				COUNT(*)  AS fiches_traitees 
				FROM " . self::TABLE . "
				WHERE 1=1 
			";
			$sql = $this->addFiltres($filtres,$sql);
			
			$req = $this->bdd->prepare($sql);
            $req->execute($tab_value);
            $result = $req->Fetch(PDO::FETCH_ASSOC);
            $req->closeCursor();
			
			$total->fiches_traitees = $result[fiches_traitees]; 
            
			//  CALCUL DU NOMBRE DE CONTACTS 
			$sql  = "
				SELECT 
				DISTINCT(COUNT('appeler'))  AS nb_contacts 
				FROM " . self::TABLE . "
				WHERE 1=1 
			";
			$sql = $this->addFiltres($filtres,$sql);
			
			$req = $this->bdd->prepare($sql);
            $req->execute($tab_value);
            $result = $req->Fetch(PDO::FETCH_ASSOC);
            $req->closeCursor();
			
			$total->nb_contacts  = $result[nb_contacts]; 
			
			
			// CALCUL DU NOMBRE APPEL TOTAL
			$sql  = "
				SELECT 
				COUNT(*) AS nombre_appels 
				FROM " . self::TABLE . "
				WHERE 1=1 
			";
			$sql = $this->addFiltres($filtres,$sql);
			
			$req = $this->bdd->prepare($sql);
            $req->execute($tab_value);
            $result = $req->Fetch(PDO::FETCH_ASSOC);
            $req->closeCursor();
			
			$total->nombre_appels = $result[nombre_appels]; 
			
			
			
			
			return $total; 
			
        } catch(Exception $e) {
            die('Erreur : '.$e->getMessage());
        }
    }
    }

Les filtres sont désormais contenus dans cette function :

private function addFiltres($filtres,$sql){
		
		if ($filtres->mois) {
			$sql  .= " AND EXTRACT(MONTH FROM  calldate) = 	".$filtres->mois ; 
		} 	

		if ($filtres->annee) {
			$sql  .= " AND EXTRACT(YEAR FROM  calldate) = 	".$filtres->annee; 
		} 
		
		if ($filtres->id_utilisateurs) {
			$sql  .= " AND id_utilisateurs = ".$filtres->id_utilisateurs;
		}
		
		return $sql;
		
	}

[www.openode.io] Enfin, un bon hébergeur pour publier ULTRA facilement des applications NODE.JS

nodeeeeee

Introduction


Avant 2018, on pouvait créer nos applications NODE.JS assez facilement en LOCAL .

Mais lorsque venait le moment de publier notre application en ligne, c’était assez la galère,il fallait soit acheter un serveur dédié assez cher, soit effectuer des méthodes complexes avec cloudant ou autres Aws pour arriver à placer son app en ligne .

Openode.io : Une seule commande, cela fonctionne de suite !


Depuis 2018, openode.io est arrivé, et enfin, ça marche et c’est facile !! Depuis le temps qu’on attendait ça !!

On s’inscrit sur openode.io, on a de suite un environnement prêt, suffit juste de lui donner un nom, c’est vraiment TROP SIMPLE ! Cette société serait basée au Texas.

En local, dans notre pc, on se rends dans le répertoire de notre site node.js .

Ensuite, on télécharge avec GIT leur programme de gestion hyper simple qui nous donne quelques commandes supplémentaires dans CMD(La ligne de commande Windows).

Une fois qu’on a installé leur programme, il suffit de taper dans notre répertoire :

openode deploy

pour envoyer l’intégralité de notre site en ligne, ça marche de suite !

Voici un exemple de moi, qui envoie mon application node.js en ligne :

deploy.jpg

Le programme deploy surveille que notre fichier package.json contient de bonnes versions de librairies :

Exemple :

{
"name": "socket-chat-example",
"version": "0.0.1",
"description": "my first socket.io app",
"dependencies": {
"express": "^4.15.2",
"mysql": "^2.16.0",
"mongoose": "^5.2.6",
"morgan": "^1.1.1"

},
"scripts": {
"start": "node index.js"
}
}

Ici , je charge la lib mongoose pour pouvoir me connecter à un base de données MONGODB et la lib mysql pour pouvoir aussi me connecter à une base de données MYSQL, tout cela en JS (le langage le plus coool et flexiiible!).

Et oui, cela veut dire qu’on peut désormais coder tout en JS, aborder des bdd relationnelles quand même, et déployer de façon ultra simple, c’est carrément TROP COOL !

Voici les 2 autres fichiers de mon app, just pour info (On voit que j’exécute des requêtes SQL dans le Javascript …)  :

index.js :


 var app = require('express')();
 var http = require('http').Server(app);
 var port = process.env.PORT || 3000;
 var mongoose = require('mongoose');
 var mysql = require('mysql');
 var morgan = require('morgan'); // log requests to the console (express4)</code>

 var connection = mysql.createConnection({
     host: 'sql.free.fr',
     user: 'nicolas.huleux',
     password: 'xxxxxxx',
     database: 'nicolas_huleux'
 });

 connection.connect(function(err) {
     // connected! (unless `err` is set)

 });

 connection.query('SELECT * from acteurs', function(err, rows, fields) {
     if (!err)
         console.log('The solution is: ', rows);
     else
         console.log('Error while performing Query.');
 });

 app.get('/', function(req, res) {
     res.sendFile(__dirname + '/index.html');
 });

 http.listen(port, function() {
     console.log('listening on *:' + port);
 });

Et là, index.html, un formulaire bateau, pas encore fonctionnel

<!doctype html>
<html>
  <head>
    <title>form</title>

  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
	
	 <form action="action_page.php">
		  <div class="imgcontainer">
			<img src="img_avatar2.png" alt="Avatar" class="avatar">
		  </div>

		  <div class="container">
			<label for="uname"><b>Username</b></label>
			<input type="text" placeholder="Enter Username" name="uname" required>

			<label for="psw"><b>Password</b></label>
			<input type="password" placeholder="Enter Password" name="psw" required>

			<button type="submit">Login</button>
			<label>
			  <input type="checkbox" checked="checked" name="remember"> Remember me
			</label>
		  </div>

		  <div class="container" style="background-color:#f1f1f1">
			<button type="button" class="cancelbtn">Cancel</button>
			<span class="psw">Forgot <a href="#">password?</a></span>
		  </div>
		</form> 

  </body>
</html>

Conclusion :
On peut désormais coder tout en NODE.JS et publier des démos sur son blog super facilement, sans acheter une serveur dédié, c’est TROP BIEN . Si on veut, plus besoin d’utiliser PHP en back end il existe des tas de libs qui permette à node de se connecter aux bases relationnelles, y compris sans faire de SQL avec par exemple KNEX.JS (https://stackoverflow.com/questions/5818312/mysql-with-node-js) :

KNEX.JS

KnexJs can be used as an SQL query builder in both Node.JS and the browser. I find it easy to use. Let try it – Knex.js

$ npm install knex--save# Then add one of the following(adding a--save) flag:
  $ npm install pg
$ npm install sqlite3
$ npm install mysql
$ npm install mysql2
$ npm install mariasql
$ npm install strong - oracle
$ npm install oracle
$ npm install mssql


var knex = require('knex')({
    client: 'mysql',
    connection: {
        host: '127.0.0.1',
        user: 'your_database_user',
        password: 'your_database_password',
        database: 'myapp_test'
    }
});

You can use it like this

knex.select('*').from('users')

or

knex('users').where({
    first_name: 'Test',
    last_name: 'User'
}).select('id')