# Material-UI docs

Voici la documentation du site HiPay Material-UI.

Avant de commencer, il faut vous familiariser avec REACT :
- https://reactjs.org/
- https://reactjs.org/docs/optimizing-performance.html

Et connaîtres les [best practices](#best-practices)


## Lancer le projet

Il faut que sur votre poste soit installés
- [node](https://nodejs.org/fr/) (minimum version LTS 8.9.4)
- [npm](https://www.npmjs.com/) (minimum version 5.6.0)

Puis lancez les commandes
```
npm install

npm start # équivaut à : npx styleguidist server
```
Le site est dispo à cette URL:
[http://localhost:6060](http://localhost:6060)

## Best practices
#### Patterns
- single "source of truth" / top>down data flow
https://reactjs.org/docs/lifting-state-up.html
https://reactjs.org/docs/state-and-lifecycle.html#the-data-flows-down

- classique patterns
https://reactpatterns.com

- accéder au thème dans un composant (en dehors du style)
export default withStyles(styles, { withTheme: true })(CellStatus);
ne plus utiliser la notation
export default withStyles(styles)(withTheme()(CellStatus));

#### Optimisation
- Faire attention au Lifecycle ! ne pas introduire de boucle infinie en "updatant" le state d'un composant dans une mauvaise phase. (voir schéma ci-dessous).
Si le composant à besoin d'accéder à son DOM (pour redéfinir sa taille...), on préfère le gérer en js pur pour ne pas refaire un cycle (voir la gestion des scrolls dans HiTable/HiTable.js ou l'ellipse au milieu dans HiTable/BodyCells/CellText.js )
<img width="800" src="/static/react-lifecycle.png" alt="react-lifecycle">

- Comprendre la différence entre React.Component & React.PureComponent
https://codeburst.io/when-to-use-component-or-purecomponent-a60cfad01a81

- Comprendre le principe de réconciliation pour optimiser les ensembles de composants (listes, tableaux...) -> use "key" !
https://reactjs.org/docs/lists-and-keys.html
https://reactjs.org/docs/reconciliation.html

- Attention aux refs et aux mutations
ex: ne pas passer une arrow fonction directement dans les props d'un composant. Même pour y inclure un index ou une valeur contextuelle !

#### Gestion des événements clavier

- **Evénement capturé** : on part sur le _KeyDown_, c'est le seul à capturer toutes les touches du clavier ([source](https://www.w3schools.com/jsref/event_onkeypress.asp))

- **Capturing** : il s'agit de la première phase par laquelle passe un événement lors de sa capture, durant celle-ci, il descend dans l’arborescence HTML en partant de l'élément racine (en React : Parent => Enfant, on peut le capturer avec _onKeyDownCapture_)

- **Bubbling** : c'est la deuxième phase par laquelle passe un événement et celle capturée par défaut lorsque l'on fait un _onKeyDown_. A ce moment, l'événement remonte vers l'élément HTML racine (en React : Enfant => Parent)

- **PreventDefault** : on l'utilisera à chaque fois qu'il faudra éviter un comportement par défaut du navigateur.

- **StopPropagation** : il permet de stopper la capture dès qu'il est appelé. Couplé au Capturing on peut, par exemple, éviter qu'un événement soit capturé dans un composant enfant.

## Contribuer

#### A savoir
- Notre projet sur JIRA : [PSYCHE - Production](https://jira.hipay.org/secure/RapidBoard.jspa?rapidView=90&projectKey=PSYCHE)
- Pour ouvrir nos features, nous utilisons [git flow](https://danielkummer.github.io/git-flow-cheatsheet/)
Après avoir cloner le projet, il faudra lancer la commande `git flow init`  **depuis la master**

```sh
git clone git@gitlab.hipay.org:backend/hipay-material-ui.git
git checkout master
git flow init
# Tapez "Entrée" pour toutes les questions
```

- Tous les composants sont dans le dossier /src.
- Nos composants HiPay doivent être préfixés par "Hi", par exemple HiTable, HiButton...
- Pour un code bien formatter, on utilise [ESLint - Prettier](#eslint-prettier)
- Pour activer ESLint sur PHPStorm : File -> Settings -> Languages & Frameworks -> Code Qaulity Tools -> ESLint -> Enable

#### Pour rajouter de la documentation dans les démos
[Lire ce guide](https://react-styleguidist.js.org/docs/documenting.html)

#### Pour rajouter des composants dans la démo
Il faut créer un dossier avec le nom du composant.<br>
Dedans, y ajouter :
- Un fichier `index.js` qui exporte le composant (sans ce fichier la démo n'apparaitra pas dans la liste).
- Un fichier `ComponentName.js` qui sera le composant lui même.
- Un fichier `ComponentName.md` qui contiendra la démo du composant. Ce fichier peut contenir plusieurs démos à la suite.


#### Workflow d'une feature
- S'affecter la tâche JIRA et la passer à "dev in progress" (projet [PSYCHE - Production](https://jira.hipay.org/secure/RapidBoard.jspa?rapidView=90&projectKey=PSYCHE))
- Ouvrir la feature via git flow

```sh
git flow feature start PSYCHE-XXX
```

- Avant de commiter ou pusher, il faut vérifier la [Definition Of Done](https://docs.google.com/spreadsheets/d/1qYanLfy2k_VYuclar3aAWSUo9b3soI48ZCjkKK83Rr0/edit?usp=drive_web&ouid=102268869535987309171)
- Les [tests unitaires](#tests) doivent passer
- La [génération des apis](#generation-des-apis) aussi
- Le code doit être bien formatter : [ESLint - Prettier](#esLint-prettier)
- Commit - suivant les conventions de rédaction des messages de commit
- Push
- Faire la demande de merge request sur la develop
- La revue se fera par un membre de l'équipe PSYCHE

##### Conventional Changelog

(optionel) installer [commitizen](https://github.com/commitizen/cz-cli) pour s'assurer de commiter selon la convention
```sh
npm install commitizen -g
```


Voici un squelette d’exemple de message de commit conventionnel :
```
<type de tâche>(<périmètre>): message court

Description complémentaire/complète

Référence/action sur un ticket définissant cette tâche
 ```

 On facilite ainsi la lecture du log d’une part, la génération automatique du changelog (ou release notes) d’autre part

Types de tâche:
- <b>fix</b>  : commit d'une correction de bug. Se traduit en <b>PATCH</b> dans le changelog
- <b>feat</b> : commit d'une nouvelle feature. Se traduit en <b>MINOR</b> dans le changelog
- <b>test</b> : commit d'un ajout ou d'une maj de tests
- <b>docs</b> : commit d'un ajout ou d'une maj de la documentation OU de l'app de démonstration
- <b>perf</b> : commit concernant l'amélioration des performances

<b>BREAKING CHANGE</b> : si un commit introduit un BREAKING CHANGE, on doit ajouter le tag BREAKING CHANGE dans le corps du commit. Ce commit peut être de n'importe quel type mais il est préférable qu'il soit lié à une feature. Se traduit en <b>MAJOR</b> dans le changelog

Périmètre (optionel): nom du composant, type de tests, page de la doc

 Exemple:
 ```
 feat(HiTable): add children rows management

Handle children rows as subtable based on the same columns as parents.

PSYCHE-XX
 ```

## Tests
Tous les composants doivent avoir leur test à côté (fichier .spec.js)
On utilise [mocha](https://mochajs.org/), [chai](http://chaijs.com/) et [enzyme](http://airbnb.io/enzyme/docs/api/)

##### Jouer tous les tests
```sh
npm run test:unit
```

##### Jouer les tests sur un seul composant
```sh
yarn run mocha packages/hipay-material-ui/src/HiRadio/HiRadio.test.js
```

#### Vérifier la couverture de code
```sh
npm run test:coverage
# ou pour avoir le rendu html :
npm run test:coverage:html
```
La couverture de code html se trouvera dans le dossier [coverage](coverage)

#### Calcul de couverture sur un seul composant
```sh
yarn cross-env NODE_ENV=test BABEL_ENV=coverage nyc mocha src/HiTable/BodyCells/CellAccount.spec.js  && nyc report -r lcovonly
```

## ESLint - Prettier
Pour le bon formattage des fichiers, on utilise [Prettier](https://prettier.io/docs/en/install.html) avec la conf EsLint
La conf se trouve dans le fichier [prettier.config.js](prettier.config.js)
Toutes les options : [https://prettier.io/docs/en/options.html](https://prettier.io/docs/en/options.html)

#### Installer prettier en global
```sh
yarn global add prettier
```

#### Utilisation [voir doc](https://prettier.io/docs/en/cli.html)

#### Vérifier le fichier de config utilisé
```sh
prettier --find-config-path src/HiForm/HiInput.js
```

#### Forcer le formatage d'un fichier
```sh
prettier --write src/HiForm/HiInput.js
```

## Publish
Le projet est publié sur un repo privé npm : https://www.npmjs.com/package/@hipay/hipay-material-ui

Un script de déploiement automatique est disponible dans gitlab CI.

#### [Semantic Versioning](https://semver.org/)

Une version MAJOR.MINOR.PATCH, correspond a:

- MAJOR version introduisant des évolutions non retro-compatibles (API changes...),
- MINOR version introduisant des évolutions retro-compatibles, la sortie des versions mineures est basé sur les sprints de la tribu PSYCHE
- PATCH version corrigeant des bugs
Des tags additionels peuvent être ajouter selon le contexte (ex: 1.0.0-beta.24).

En production, chaque releases (MAJOR, MINOR & PATCH) doit faire l'objet d'une communication interne aux tribus utilisatrices.

Les projets peuvent se baser sur une version MINOR: ```^2.5.0```, ce qui signifient "compatible avec la version 2.5.0".

Ainsi les PATCH seront automatiquement pris en compte.
L'intégration d'une MINOR doit faire l'objet d'une recette (voir HI-CHANGELOG.md).
Le passage à une autre MAJOR doit faire l'objet d'une recette (voir HI-CHANGELOG.md BREAKING CHANGE).

## Importer la lib dans son projet React

Le package est publié sur un repo npm privé.

Il est donc nécessaire d'ajouter le token d'authentification dans le fichier ``.npmrc``.

Demander à l'équipe PSYCHE ou le copier depuis le projet [console](https://gitlab.hipay.org/backend/console/blob/feature/common-notice/.npmrc).

# Si ERR d'authentification
npm adduser
admin
admin123

# pour le premier publish, modifier .npmrc
vi ~/.npmrc
# Mettre
registry=http://jira-nexus.hipay-pos-platform.com:8081/repository/npm-private/
_auth="YWRtaW46YWRtaW4xMjM="
```

## Troubleshooting

### Upgrade node :
```sh
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
```

### Lorsqu'on lance la commande pour générer les apis :
Erreur : Cannot read property 'name' of undefined
=> Une props est présente dans les défaultProps mais pas déclarée dans propTypes

### Lorsqu'on rajoute une page demo :
**Cannot read property 'js' of undefined**
=> dans le fichier markdown du dossier docs/src/pages/demos/[VOTRE-DEMO]/votre-demo.md, la demo pointe sur un fichier qui n'existe pas.
Ou bien la demo n'existe pas dans le fichier js du dossier pages/demos/votre-demo.js

**Cannot read property 'toLowerCase' of undefined**
=> un composant qu'on importe n'est pas exporter. Vérifier le fichier index.js à la racine du dossier du composant en question dans src/

**Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of `SelectSuggestWithLabel`.**
=> on importe mal un composant, par exemple
```import { HiFormControl } from 'material-ui/Form';```
au lieu de
```import { HiFormControl } from 'hipay-material-ui/HiForm';```

### Problème d'import dans front-react
Attention aux index.js.
La bonne syntaxe est :
export { default as MyComponente } from './MyComponente';

[source]: https://www.w3schools.com/jsref/event_onkeypress.asp