Skip to content
Snippets Groups Projects
Commit 4d7f374c authored by Loïc Poullain's avatar Loïc Poullain
Browse files

Re-factor documentation

parent 0dd2cf89
Branches
No related tags found
1 merge request!110[IR] Améliorer la carte Gagnants Perdants et mettre à jour doc
# Introduction
# LexImpact Client
## [FR] Introduction
## Introduction
Ceci est le code source de l'interface utilisateur de LexImpact.
LexImpact est un service de l'Assemblée nationale fournissant des outils de simulations fiscales, financières et sociales à destination des députés, administrateurs et collaborateurs. Ils sont accessibles via l'URL [https://leximpact.an.fr](https://leximpact.an.fr).
LexImpact permet aux administrations, aux parlementaires et à la société civile de simuler l'impact _ex ante_ des réformes au système socio-fiscal.
* [Appels à candidatures](https://entrepreneur-interet-general.etalab.gouv.fr/defis/2019/leximpact.html)
* [Fiche produit](https://beta.gouv.fr/startups/leximpact.html)
* [LexImpact](https://leximpact.an.fr)
Ce dépôt contient le code du *front*. Les technologies principalement utilisées sont TypeScript, redux et React (Next.js).
LexImpact est constitué de deux parties :
![Screenshot](./screenshot.png)
- [leximpact-server](https://github.com/betagouv/leximpact-server/) : application en python utilisant [OpenFisca-France](https://github.com/openfisca/openfisca-france) permettant de mettre en place une API Web répondant à des questions sur l'impact de modifications de la loi fiscale,
- Ici même, [leximpact-client](https://github.com/betagouv/leximpact-client/) : interface web communiquant avec l'API qui met à disposition des usagers un site web permettant de définir des modifications de la loi et d'en visulaliser les résultats calculés par l'API.
## Configuration de l'environnement
| Version Node | Version npm |
| --- | --- |
| 12.x | 6.13 |
## [EN] Introduction
Installez les dépendances.
This is the source code of LexImpact user interface.
```
npm install
```
LexImpact allows civil servants, policy makers and citizens to simulate the _ex ante_ impact of a reform to a country's tax-benefit system.
* [Call for candidates (FR)](https://entrepreneur-interet-general.etalab.gouv.fr/defis/2019/leximpact.html)
* [Elevator pitch (FR)](https://beta.gouv.fr/startups/leximpact.html)
* [LexImpact](https://leximpact.an.fr)
Exécutez les tests.
LexImpact has two components:
```
npm run test
```
- [leximpact-server](https://github.com/betagouv/leximpact-server/): a Python application using [OpenFisca-France](https://github.com/openfisca/openfisca-france) and providing a Web API responding to requests on the impact of a change of the tax law,
- Here, [leximpact-client](https://github.com/betagouv/leximpact-client/): a web interface interacting with leximpact-server API and providing to the users a web site to set law tax changes and see the results calculated by the API.
Vérifiez le *linting* du code.
## Organisation de l'état de l'application
```
npm run code:check
```
![Etat de l'application](./redux-state.png)
Compilez et lancez l'application en développement (*watch mode*).
```
npm run dev
```
Alternativement, vous pouvez aussi compiler et lancer l'application séparément (pour une CI ou la production).
```
npm run build
npm run start
```
L'état redux est en cours de re-factorisation. Voici la manière dont il se présentera à terme:
## Structure des fichiers
### Organisation des composants
```bash
- common # Composants communs à toutes les pages
- dotations # Composants spécifiques à la page dotations
- common # Composants communs à plusieurs parties de la page
- articles # Section paramètres à gauche
- results # Resultats à droite
- common
- ...
- ir # Composants spécifiques à la page ir
- ... # Composants spécifiques à la page ...
```
### Organisation de l'état de l'application
![Etat de l'application](./redux-state.png)
```bash
- parameters # Paramètres de loi modifiables (panneau latéral de gauche)
......@@ -43,7 +73,7 @@ L'état redux est en cours de re-factorisation. Voici la manière dont il se pr
- base # Valeurs présentes dans le code en vigueur
- ir
- dotations
- plf # Valeurs proposées par le Projet de Loi des Finances
- plf # Valeurs proposées par le Projet de loi de finances
- ir
- dotations
- interfaces # Descriptions des états (identiques dans amendement, base et plf)
......@@ -56,7 +86,7 @@ L'état redux est en cours de re-factorisation. Voici la manière dont il se pr
- base # Résultats correspondant aux valeurs du code en vigueur
- ir
- dotations
- plf # Résultats correspondant aux valeurs proposées par le Projet de Loi des Finances
- plf # Résultats correspondant aux valeurs proposées par le Projet de loi de finances
- ir
- dotations
- baseToPlf # Résultats comparant le PLF avec le code existant
......@@ -79,30 +109,7 @@ L'état redux est en cours de re-factorisation. Voici la manière dont il se pr
- dotations
```
Les données asynchrones (comme les résultats de la simulation) sont décrites par cette interface:
```typescript
export interface AsyncState<T> {
isFetching: boolean;
state: T | null;
}
```
## Organisation des composants
```bash
- common # Composants communs à toutes les pages
- dotations # Composants spécifiques à la page dotations
- common # Composants communs à plusieurs parties de la page
- articles # Section paramètres à gauche
- results # Resultats à droite
- common
- ...
- ir # Composants spécifiques à la page ir
- ... # Composants spécifiques à la page ...
```
## Ajouter d'un composant avec un état
## Architecture d'un composant
```typescript
interface Props {
......@@ -113,7 +120,7 @@ const mapStateToProps = (state: RootState) => ({
// ...
});
const mapDispatchToProps = (dispatch, { name }: Props) => ({
const mapDispatchToProps = (dispatch, { /* ... */ }: Props) => ({
// ...
});
......@@ -131,15 +138,6 @@ export { Component as Foobar };
```
## How to use
To install and launch the client in developer mode, run the following commands:
```shell
npm install
npm run dev
```
## Configuration file `.env`
A file name `.env` is necessary for the client to work properly. The file `.env.example` can be copied into it.
......@@ -148,14 +146,7 @@ Here ate the environment variables that you have to set:
- `API_URL`: leximpact-client is just a web interface that does not do computations by itself, but needs to be provided a working [leximpact-server](https://github.com/betagouv/leximpact-server/) Web API to fetch results. As of v`1.0.0`, a working API example can be found on: https://api.leximpact.an.fr
- `PORT`: describes the port that the client will be setup to (e.g. the website will be accessible from http://127.0.0.1:<PORT> if the client is run locally). If ommited, defaults to `9001`
# Affichage du PLF
L'affichage du PLF est contrôlé par l'état redux `parameters.plf` et par l'état `results.casTypes`.
- Pour afficher les valeurs des paramètres, vous devez définir la variable `PLF_DEFAULT_STATE` comme valeur par défaut de l'état dans `parameters/plf.ts`.
- Pour afficher les résultats, la réponse de l'API doit inclure une propriété `plf` (voir documentation côté serveur).
# Snapshot testing with Jest
## Snapshot testing with Jest
Snapshot tests are a very useful tool whenever you want to make sure your UI does not change unexpectedly.
......@@ -177,16 +168,3 @@ npm run test --updateSnapshots
```
This is similar to: `./node_modules/.bin/jest --updateSnapshots`
# Screenshot
<img width="1280" alt="Capture d’écran 2019-11-06" src="https://user-images.githubusercontent.com/17675313/68288289-6a75a780-0084-11ea-9bab-addb613cd2a4.png">
# Icons & Emoji sources
- [Twitter Emoji](https://iconify.design/icon-sets/twemoji/)
- [MaterialUI Icons](https://material.io/resources/icons)
# Documentation
- [MaterialUI v3.9.9 Documentation](https://v3.material-ui.com/getting-started/installation/)
# Principes Redux (Action, Reducer, Dispatch...)
Le concept Redux peut se résumer par
- `action, réaction, observer`
ou encore
- `abonnement, observer`
![Redux Schéma](https://www.softfluent.fr/blog/expertise/118329abbbfe_A564_ReduxGraph_e45016dc-618e-405e-9470-0712f613547c.png)
## En résumé
1. je clique sur composant (_view_)
2. cela dispatch une action avec un type (_dispatch_ / _mapDispatchToProps_)
3. réception dans un ou plusieurs reducers, modification en regard d'un `(action.type)` si nécessaire (_reducer_)
4. les vues connectées sont automatiquement mise à jour avec les nouvelles valeur des reducers (_store_ / _mapStateToProps_)
## Les Reducers
Les reducers servent de stockage des informations
Par exemple on dit qu'ils sont _abonnés_ au dispatcher par des _action.type_
Les reducers prennent en arguments
- l'etat précédent/actuel de ce reducer (state)
- un objet action contentant obligatoirement une propriété `type`
Exemple ci dessous avec l'état de chargement d'une application
```javascript
const monReducerLoading = (etatPrecedent, action) => {
let etatChargement = etatPrecedent;
switch (action.type) {
case "enCoursDeChargement":
etatChargement = true;
return etatChargement;
case "finDuChargement":
etatChargement = false;
return etatChargement;
default:
return etatChargement;
}
};
```
Dans un composant/vue connecté on aura donc accès à la valeur de `monReducerLoading` dans la méthode `mapStateToProps`
```javascript
const mapStateToProps = state => {
const { monReducerLoading } = state;
return {
isLoading: monReducerLoading === true,
};
};
export default connect(mapStateToProps)(monComposant);
```
## Les actions
Les actions permettent de faire le pont entre un composant connecté _connect_ et les reducers
Ce sont des fonctions basiques, qui au minimum doivent retourner une `action.type`, une chaine de caractère, un identifiant qui permettra d'agir en fonction dans un reducer.
Ce pattern est aussi connu sous le nom de _signal_, cela est comparable aux différentes fréquences radio
- Mon auto radio est sur la fréquence 107,7 je capte les Infos Autoroute
- Mais je ne peux pas capter pas Radio Nostalgie qui est sur une autre fréquence
Elles doivent retourner un objet
Les actions peuvent transmettre d'autres arguments au reducer en plus du type (optionnel)
```javascript
const monActionDeClickBouton = argumentOptionnel => {
return {
type: "QuandJaiCliqueSurLeBoutonJeDoisFaireX",
argumentOptionnel,
};
};
// Notation courte
// const monActionDeClickBouton = (argumentOptionnel) => ({
// type: 'QuandJaiCliqueSurLeBoutonJeDoisFaireX'
// argumentOptionnel
// });
export default monActionDeClickBouton;
```
## Description d'un composant connecté à Redux
**Un composant connecté se compose de deux fichiers**
#### `./mon-fichier-component.jsx` (_vue_)
Un composant contenant uniquement de l'affichage ou de l'expérience user (click et autres actions faites par l'user)
#### `./index.js` (_connecteur_)
Ce fichier va connecter un composant à Redux, via la méthode `connect`
Exemple:
```javascript
export default connect(
mapStateToProps,
mapDispacthToProps
)(MonFichierComponent);
```
## Description du fichier `index.js` (_connecteur_)
#### La méthode `mapStateToProps` (_récepteur_)
Elle correspond au store dans le schéma ci dessus
C'est dans cette fonction que l'on va affecter de nouvelles props
Qui seront créées en fonction de l'état d'un ou plusieurs reducers en particulier, _je suis en train de charger, désactive le bouton_ par exemple
Elle recoit en arguments:
- Tous les reducers
- Les props du composant passées depuis le composant contenant/parent (optionnel)
Elle doit retourner un objet de props `return { disabled, prop1, prop2 }`
Exemple:
```javascript
const mapStateToProps = ({ loading, loadingEtat, ... }, props) => {
const isDisabled = loading && loadingEtat
return { isDisabled }
}
export default connect(
mapStateToProps,
mapDispacthToProps
)(MonFichierComponent);
```
#### La méthode `mapDispatchToProps` (_émétteur_)
Elle correspond au dispatch dans le schéma ci dessus
Permet de connecter les actions user depuis la vue vers les reducers, par le biais des _actions_
C'est dans cette fonction que l'on va définir des fonctions qui seront appelées depuis la _vue_ et qui doivent avoir un impact sur la globalité de l'application
Cela permet ainsi de connecter différentes vues entre elles sans qu'il ait connaissance les unes des autres
Elle reçoit en arguments
- une function `dispatch`
- Les props du composant passées depuis le composant contenant/parent (optionnel)
Elle retourne un objet contenant uniquement des fonctions
Ces fonctions vont permettre de _dispatcher_ des actions afin de modifier les reducers
Préfixer ces fonctions avec `handle` cela rendra le code d'un composant plus lisible
Ces fonctions acceptent des arguments provenant de la vue (optionnel)
```javascript
const mapStateToProps = () => {};
const mapDispatchToProps = (dispatch, props) => ({
handleJaiCliqueSurLaBoutonX: () => {
dispatch(jaiCliqueSurLaBoutonX());
},
handleJaiCliqueSurLaBoutonY: couleurApplicable => {
const couleur = couleurApplicable;
dispatch(jaiCliqueSurLaBoutonY(couleur));
},
});
export default connect(
mapStateToProps,
mapDispacthToProps
)(MonFichierComponent);
```
screenshot.png

327 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment