Formatage de code avec husky et prettier

Petit point rapide pour la mise en place d’un formatage automatique des portions de code modifiées au moment du commit (en environnement JS : Angular/Node).

Installation des dépendances :

npm install --save-dev husky prettier precise-commits

Configuration à ajouter dans package.json :

"husky": {
"hooks": {
"pre-commit": "precise-commits"
}
},

À noter que prettier n’arrive pas toujours à formater un extrait de fichier JSON, l’intérêt de precise-commits peut s’en voir grandement diminuer si le projet contient de nombreux fichiers JSON régulièrement modifiés.

COBOL : COMPUTE ROUNDED

Une petite notion de COBOL pour par exemple trouver quelques centimes par ci, quelques centimes par là.

Il s’agit de l’utilisation du paramètre ROUNDED dans l’écriture d’un COMPUTE

Les variables

01 W-NOMBRE1 PIC S9(15)V99 COMP-3.
01 W-NOMBRE2 PIC S9(15)V99 COMP-3.
01 W-MULTIPLICATEUR PIC S9(3)V9(6) COMP-3.
01 W-RESULTAT1 PIC S9(15)V99 COMP-3.
01 W-RESULTAT2 PIC S9(15)V99 COMP-3.
01 W-EDIT9 PIC +ZZZ.ZZZ.ZZZ.ZZZ.ZZ9,99.

Le code d’exemple

DISPLAY '----------ROUNDED DEBUT -------------'
MOVE 123,12 TO W-NOMBRE1
MOVE 567,56 TO W-NOMBRE2
MOVE 456,456789 TO W-MULTIPLICATEUR
MOVE 0 TO W-RESULTAT1
MOVE 0 TO W-RESULTAT2

COMPUTE W-RESULTAT1 ROUNDED = W-NOMBRE1
* W-NOMBRE2
* W-MULTIPLICATEUR

COMPUTE W-RESULTAT2 = W-NOMBRE1
* W-NOMBRE2
* W-MULTIPLICATEUR

MOVE W-RESULTAT1 TO W-EDIT9
DISPLAY 'ROUNDED    : ' W-EDIT9

MOVE W-RESULTAT2 TO W-EDIT9
DISPLAY 'NOT ROUNDED: ' W-EDIT9

MOVE 0 TO W-RESULTAT1
MOVE 0 TO W-RESULTAT2

COMPUTE W-RESULTAT1 ROUNDED = W-NOMBRE1
* W-NOMBRE2
- W-MULTIPLICATEUR

COMPUTE W-RESULTAT2 = W-NOMBRE1
* W-NOMBRE2
- W-MULTIPLICATEUR

MOVE W-RESULTAT1 TO W-EDIT9
DISPLAY 'ROUNDED    : ' W-EDIT9

MOVE W-RESULTAT2 TO W-EDIT9
DISPLAY 'NOT ROUNDED: ' W-EDIT9

DISPLAY '----------ROUNDED FIN -------------'

La sysout

----------ROUNDED DEBUT -------------
ROUNDED    : + 31.896.281,66
NOT ROUNDED: + 31.896.281,65
ROUNDED    : + 69.421,53
NOT ROUNDED: + 69.421,53
----------ROUNDED FIN -------------

Résultats réels

Pour le premier calcul : 31.896.281,6590951

Pour le second : 69421,530411

Conclusion

Comme l’explique la documentation Cobol, ROUNDED arrondi la dernière décimale en l’augmentant de 1 si la décimale suivante en trop dépasse ou est égale à 5. Vrai dans le premier calcul faut dans le second.

Notez que le comportement normal est la troncature des décimaux en trop par rapport à la variable de réception du COMPUTE.

Installation d’un package npm depuis un dépôt GitLab

Pour utiliser un dépôt hébergé sur sa propre instance GitLab, rien de bien compliquer, si ce n’est le protocole à utiliser : git+https et pas juste https (ou git+http au lieu de http).

Ce qui nous donne pour la branche master d’un projet :

{
  ...
  "dependencies": {
    "mon-projet": "git+https://<mon-domaine-gitlab>/<user>/<mon-projet>#master",
    ...
  }
}

Illustration pour récupérer une configuration eslint sous forme de module dans son dépôt propre :

{
  ...
  "devDependencies": {
    "eslint-config-unicoda": "git+https://gitlab.unicoda.com/vvision/javascript-convention#master",
    ...
  }
}

Rafraichir la page parente à la fermeture de la page fille

Derrière ce titre alambiqué se cache un besoin particulier que j’ai cherché (et réussi) à résoudre dernièrement. La situation est la suivante : un utilisateur arrive sur une page, celle-ci effectue un appel ajax afin de connaître l’état d’un paramètre utilisateur. Pour illustrer, nous dirons donc que la page interroge une api pour répondre à la question : l’utilisateur a-t-il une image de profil enregistrée ?

Si l’utilisateur possède une image enregistrée, on la lui affiche ainsi qu’un message pour lui permettre de la supprimer. Si aucune image n’est présente, l’utilisateur peut choisir d’en ajouter une. L’acquisition de l’image s’effectue dans une page dédiée, que nous appellerons la page fille. Cette acquisition est réalisée à l’aide de la bibliothèque Cropper.js.

Une fois l’image acquise, l’utilisateur valide la sélection via un bouton. Au niveau de la page fille, un appel est donc réalisé vers une api pour sauvegarder l’image. Si l’appel est une réussite, nous fermons la page fille. À ce stade, l’utilisateur se retrouve sur la page parente qui lui propose toujours d’ajouter une image, ce qu’il vient de faire, nous allons donc recharger la page parente à la fermeture de la page fille.

J’illustre ce processus dans le code HTML en fin de page. Lorsque la page parente est chargée, celle-ci affiche en alert(), le message « Page chargée ! » afin de matérialiser le rechargement de la page. En cliquant sur le lien, une nouvelle page s’ouvre. Lorsqu’on clique sur le bouton de cette page, on va déclencher la fermeture de la page courante (la page fille) et le rechargement de la page parente. De plus, afin de matérialiser l’action de la page fille dans la page parente, de rendre l’exemple plus intéressant et de matérialiser ce qui correspondrait dans mon cas pratique à la mise à jour de l’information par le premier appel ajax (celui sur la page parente), le texte saisi dans le formulaire sur la page fille est transféré à la page parente et affiché par un alert().

Par ailleurs, le test du booléen pageFille.fermeture dans la fonction de l’événement unload de la page fille permet de s’assurer que la page parente ne sera rechargée que si le traitement est réussi sur la page fille où window.fermeture vaudra alors true. En effet, si on enlève le test du booléen, on constate qu’un événement unload a lieux dès l’ouverture de la page fille, ce qui aurait donc pour effet de recharger immédiatement la page parente. Le test du booléen permet de palier à ce « problème ».

Page Parente (pageParente.html)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <p>
      <a href="javascript:ouvrirPageFille();">cliquez ici</a>
    </p>

    <script>
      function ouvrirPageFille() {
        var pageFille = window.open('pageFille.html', 'Titre', 'top=42,left=42,height=800,width=600,scrollbars=yes,status=no,toolbar=yes');
        //Recharge la page parente à la fermeture de la page fille 
        pageFille.onunload = function() {
          if(pageFille.fermeture) {
            alert(pageFille.message);
            //Rechargement
            location.reload();
          }
        }
      }

      window.onload = alert('Page chargée !');
    </script>
  </body>
</html>

Page Fille (pageFille.html)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
  </head>
  <body>
    <form>
      <label for="message">Message :</label>
      <input id="message" type="text" name="message">
      <input type="submit" value="Valider et quitter" onclick="quitterPage();">
    </form>

    <script>
      function quitterPage() {
        window.message = document.getElementById('message').value;
        window.fermeture = true;
        window.close();
      }
    </script>
  </body>
</html>

Voilà pour l’exemple. Il reste maintenant quelques limitations à préciser pour finir cet article. Si l’utilisateur ferme la fenêtre du navigateur via le bouton prévu à cet effet (la croix rouge généralement en haut à droite), la page parente n’est pas rechargée. Dans mon cas pratique, cela fait sens car l’utilisateur n’aura alors pas soumit d’image; il n’y a donc aucun raison de rafraîchir la page. Autre point, si l’utilisateur rafraîchit la page fille, cela a pour effet de casser la liaison existante entre les deux pages et le rechargement de la page parente n’aura pas lieux.

Voici donc une manière de rafraîchir une page parente à la fermeture de sa page fille en restant dans les fonctionnalités de base du navigateur et des langages. D’autres façons de faire sont très certainement possibles (avec des événements) et certains framework js seraient à même de simplifier le problème, en permettant de ne mettre à jour dynamiquement qu’une partie de l’interface.

[SQL] DROP CREATE « pattern » (MSSQL)

Simple reminder for a working drop-create pattern in SQL (Successfully used with MSSQL).

Log modification in table _chgLog first.

INSERT INTO _chgLog ([Date], [Version], [txt], [Type])
    VALUES (GETDATE(), '0.0.1', 'Update example', 0)
GO

If object exists, we drop it before doing anything (But do not drop table unless you don’t care about data).

IF OBJECTPROPERTY(object_id('example'), N'IsProcedure') = 1
    DROP PROCEDURE [dbo].[example]
GO

Other interesting parameters for function objectproperty are the following (more to be found here) :

  • IsInlineFunction
  • IsProcedure
  • IsScalarFunction
  • IsTable
  • IsTableFunction
  • IsTrigger
  • IsView

Then, we create the object.

-- =============================================
-- Author: vvision
-- Create date: 22/03/2016
-- Description: <Description>
-- =============================================

CREATE PROCEDURE [dbo].[example]
  @id INT,
AS
  SELECT *
  FROM [dbo].[example]
  WHERE id = @id
GO

Finally, we give permissions to users if needed.

GRANT EXECUTE ON [dbo].[example] TO [user] AS [dbo]
GO

 

On another subject, to alter a table, we can use:

IF COL_LENGTH('table','newField') IS NULL
BEGIN
  ALTER TABLE [dbo].[table] ADD newField VARCHAR(128) NULL
END