From 221100e8422d5c5c5c5b4ba5aa0778ef4903a702 Mon Sep 17 00:00:00 2001
From: maxime
Date: Fri, 16 Feb 2024 19:54:07 +0100
Subject: [PATCH] configure eslint
---
.eslintrc.cjs | 30 +++---
.eslintrc.js | 29 +++---
.php-cs-fixer.php | 16 ---
.prettierrc | 12 +--
Documentation/Conception.md | 53 +++++-----
Documentation/Description.md | 21 ++--
Documentation/README.md | 6 +-
Documentation/how-to-dev.md | 56 +++++-----
README.md | 2 +
ci/.drone.yml | 97 +++++++-----------
index.html | 20 ++--
package.json | 79 ++++++++-------
src/App.tsx | 41 +++++---
src/Fetcher.ts | 25 ++---
src/api/failure.ts | 4 +-
src/api/session.ts | 2 +-
src/components/TitleInput.tsx | 4 +-
src/components/editor/CourtBall.tsx | 2 +-
src/index.css | 2 -
src/main.tsx | 13 ++-
src/pages/404.tsx | 17 ++--
src/pages/CreateTeamPage.tsx | 3 +-
src/pages/Editor.tsx | 106 +++++++++++--------
src/pages/HomePage.tsx | 15 +--
src/pages/LoginPage.tsx | 86 +++++++++++-----
src/pages/NewTacticPage.tsx | 23 +++--
src/pages/RegisterPage.tsx | 152 +++++++++++++++++++---------
src/pages/TeamPanel.tsx | 65 ++++++------
src/pages/Visualizer.tsx | 46 ++++-----
src/pages/template/Header.tsx | 39 +++----
src/style/app.css | 2 +-
src/style/form.css | 16 +--
src/style/template/header.css | 5 +-
tsconfig.json | 43 ++++----
tsconfig.node.json | 18 ++--
vite.config.ts | 29 +++---
36 files changed, 651 insertions(+), 528 deletions(-)
delete mode 100644 .php-cs-fixer.php
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index d6c9537..3961d0a 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -1,18 +1,18 @@
module.exports = {
- root: true,
- env: { browser: true, es2020: true },
- extends: [
- 'eslint:recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:react-hooks/recommended',
- ],
- ignorePatterns: ['dist', '.eslintrc.cjs'],
- parser: '@typescript-eslint/parser',
- plugins: ['react-refresh'],
- rules: {
- 'react-refresh/only-export-components': [
- 'warn',
- { allowConstantExport: true },
+ root: true,
+ env: { browser: true, es2023: true },
+ extends: [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react-hooks/recommended",
],
- },
+ ignorePatterns: ["dist", ".eslintrc.cjs"],
+ parser: "@typescript-eslint/parser",
+ plugins: ["react-refresh"],
+ rules: {
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ },
}
diff --git a/.eslintrc.js b/.eslintrc.js
index 16f7f84..062a82e 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,23 +1,22 @@
module.exports = {
root: true,
- parser: '@typescript-eslint/parser',
- plugins: [
- '@typescript-eslint',
- 'react',
- 'react-hooks'
- ],
+ parser: "@typescript-eslint/parser",
+ plugins: ["@typescript-eslint", "react", "react-hooks"],
extends: [
- 'eslint:recommended',
- 'plugin:@typescript-eslint/recommended',
- 'plugin:react/recommended',
- 'plugin:react/jsx-runtime',
- 'plugin:react-hooks/recommended'
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react/recommended",
+ "plugin:react/jsx-runtime",
+ "plugin:react-hooks/recommended",
],
rules: {
+ "prefer-const": ["error", {
+ "destructuring": "all"
+ }]
},
settings: {
react: {
- version: 'detect'
- }
- }
-};
\ No newline at end of file
+ version: "detect",
+ },
+ },
+}
diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php
deleted file mode 100644
index 77ef0e7..0000000
--- a/.php-cs-fixer.php
+++ /dev/null
@@ -1,16 +0,0 @@
-in(__DIR__);
-
-return (new PhpCsFixer\Config())
- ->setRules([
- '@PER-CS' => true,
- '@PHP74Migration' => true,
- 'array_syntax' => ['syntax' => 'short'],
- 'braces_position' => [
- 'classes_opening_brace' => 'same_line',
- 'functions_opening_brace' => 'same_line'
- ]
- ])
- ->setIndent(" ")
- ->setFinder($finder);
diff --git a/.prettierrc b/.prettierrc
index 7db0434..2b63492 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,7 +1,7 @@
{
- "bracketSameLine": true,
- "trailingComma": "all",
- "printWidth": 80,
- "tabWidth": 4,
- "semi": false
-}
\ No newline at end of file
+ "bracketSameLine": true,
+ "trailingComma": "all",
+ "printWidth": 80,
+ "tabWidth": 4,
+ "semi": false
+}
diff --git a/Documentation/Conception.md b/Documentation/Conception.md
index 177be45..31249e0 100644
--- a/Documentation/Conception.md
+++ b/Documentation/Conception.md
@@ -4,25 +4,27 @@
Notre projet est divisé en plusieurs parties:
-- `src/API`, qui définit les classes qui implémentent les actions de l’api
-- `src/App`, qui définit les contrôleurs et les vues de l’application web
-- `src/Core`, définit les modèles, les classes métiers, les librairies internes (validation, http), les gateways, en somme, les élements logiques de l’application et les actions que l’ont peut faire avec.
-- `sql`, définit la base de donnée utilisée, et éxécute les fichiers sql lorsque la base de donnée n’est pas initialisée.
-- `profiles`, définit les profiles d’execution, voir `Documentation/how-to-dev.md` pour plus d’info
-- `front` contient le code front-end react/typescript
-- `ci` contient les scripts de déploiement et la définition du workflow d’intégration continue et de déploiement constant vers notre staging server ([maxou.dev//public/](https://maxou.dev/IQBall/master/public)).
-- `public` point d’entrée, avec :
- - `public/index.php` point d’entrée pour la webapp
- - `public/api/index.php` point d’entrée pour l’api.
+- `src/API`, qui définit les classes qui implémentent les actions de l’api
+- `src/App`, qui définit les contrôleurs et les vues de l’application web
+- `src/Core`, définit les modèles, les classes métiers, les librairies internes (validation, http), les gateways, en somme, les élements logiques de l’application et les actions que l’ont peut faire avec.
+- `sql`, définit la base de donnée utilisée, et éxécute les fichiers sql lorsque la base de donnée n’est pas initialisée.
+- `profiles`, définit les profiles d’execution, voir `Documentation/how-to-dev.md` pour plus d’info
+- `front` contient le code front-end react/typescript
+- `ci` contient les scripts de déploiement et la définition du workflow d’intégration continue et de déploiement constant vers notre staging server ([maxou.dev//public/](https://maxou.dev/IQBall/master/public)).
+- `public` point d’entrée, avec :
+ - `public/index.php` point d’entrée pour la webapp
+ - `public/api/index.php` point d’entrée pour l’api.
## Backend
### Validation et résilience des erreurs
+
#### Motivation
-Un controlleur a pour but de valider les données d'une requête avant de les manipuler.
+
+Un controlleur a pour but de valider les données d'une requête avant de les manipuler.
Nous nous sommes rendu compte que la vérification des données d'une requête était redondante, même en factorisant les différents
-types de validation, nous devions quand même explicitement vérifier la présence des champs utilisés dans la requête.
+types de validation, nous devions quand même explicitement vérifier la présence des champs utilisés dans la requête.
```php
public function doPostAction(array $form) {
@@ -39,11 +41,11 @@ public function doPostAction(array $form) {
if (Validation::isLenBetween($email, 6, 64))) {
$failures[] = "L'adresse email doit être d'une longueur comprise entre 6 et 64 charactères.";
}
-
+
if (!empty($failures)) {
return ViewHttpResponse::twig('error.html.twig', ['failures' => $failures]);
}
-
+
// traitement ...
}
```
@@ -56,9 +58,10 @@ Bien souvent, lorsque le prédicat échoue, un message est ajouté à la liste d
de la redondance sur les messages d'erreurs choisis lorsqu'une validation échoue.
#### Schéma
+
Toutes ces lignes de code pour définir que notre requête doit contenir un champ nommé `email`, dont la valeur est une adresse mail, d'une longueur comprise entre 6 et 64.
Nous avons donc trouvé l'idée de définir un système nous permettant de déclarer le schéma d'une requête,
-et de reporter le plus d'erreurs possibles lorsqu'une requête ne valide pas le schéma :
+et de reporter le plus d'erreurs possibles lorsqu'une requête ne valide pas le schéma :
```php
public function doPostAction(array $form): HttpResponse {
@@ -66,17 +69,18 @@ public function doPostAction(array $form): HttpResponse {
$req = HttpRequest::from($form, $failures, [
'email' => [DefaultValidators::email(), DefaultValidators::isLenBetween(6, 64)]
]);
-
+
if (!empty($failures)) { //ou $req == null
return ViewHttpResponse::twig('error.html.twig', ['failures' => $failures])
}
-
+
// traitement ...
}
```
+
Ce système nous permet de faire de la programmation _déclarative_, nous disons à _quoi_ ressemble la forme de la requête que l'on souhaite,
plustot que de définir _comment_ réagir face à notre requête.
-Ce système permet d'être beaucoup plus clair sur la forme attendue d'une requête, et de garder une lisibilité satisfaisante peu importe le nombre de
+Ce système permet d'être beaucoup plus clair sur la forme attendue d'une requête, et de garder une lisibilité satisfaisante peu importe le nombre de
champs que celle-ci contient.
Nous pouvons ensuite emballer les erreurs de validation dans des `ValidationFail` et `FieldValidationFail`, ce qui permet ensuite d'obtenir
@@ -84,40 +88,41 @@ plus de précision sur une erreur, comme le nom du champ qui est invalidé, et q
les erreurs et facilement entourer les champs invalides en rouge, ainsi que d'afficher toutes les erreurs que l'utilisateur a fait, d'un coup.
### HttpRequest, HttpResponse
+
Nous avons choisi d'encapsuler les requêtes et les réponses afin de faciliter leur manipulation.
Cela permet de mieux repérer les endroits du code qui manipulent une requête d'un simple tableau,
-et de garder à un seul endroit la responsabilitée d'écrire le contenu de la requête vers client.
+et de garder à un seul endroit la responsabilitée d'écrire le contenu de la requête vers client.
`src/App` définit une `ViewHttpResponse`, qui permet aux controlleurs de retourner la vue qu'ils ont choisit.
C'est ensuite à la classe `src/App/App` d'afficher la réponse.
### index.php
+
Il y a deux points d'entrés, celui de la WebApp (`public/index.php`), et celui de l'API (`public/api/index.php`).
Ces fichiers ont pour but de définir ce qui va être utilisé dans l'application, comme les routes, la base de donnée, les classes métiers utilisés,
-comment gérer l'authentification dans le cadre de l'API, et une session dans le cadre de la web app.
+comment gérer l'authentification dans le cadre de l'API, et une session dans le cadre de la web app.
L'index définit aussi quoi faire lorsque l'application retourne une réponse. Dans les implémentations actuelles, elle délègue simplement
l'affichage dans une classe (`IQBall\App\App` et `IQBall\API\API`).
### API
+
Nous avons définit une petite API (`src/Api`) pour nous permettre de faire des actions en arrière plan depuis le front end.
Par exemple, l'API permet de changer le nom d'une tactique, ou de sauvegarder son contenu.
C'est plus pratique de faire des requêtes en arrière-plan plustot que faire une requête directement à la partie WebApp, ce qui
aurait eu pour conséquences de recharger la page
-
## Frontend
### Utilisation de React
Notre application est une application de création et de visualisation de stratégies pour des match de basket.
L’éditeur devra comporter un terrain sur lequel il est possible de placer et bouger des pions, représentant les joueurs.
-Une stratégie est un arbre composé de plusieurs étapes, une étape étant constituée d’un ensemble de joueurs et d’adversaires sur le terrain,
+Une stratégie est un arbre composé de plusieurs étapes, une étape étant constituée d’un ensemble de joueurs et d’adversaires sur le terrain,
aillant leur position de départ, et leur position cible, avec des flèches représentant le type de mouvement (dribble, écran, etc) effectué.
les enfants d’une étape, sont d’autres étapes en fonction des cas de figures (si tel joueur fait tel mouvement, ou si tel joueur fait telle passe etc).
-Pour rendre le tout agréable à utiliser, il faut que l’interface soit réactive : si l’on bouge un joueur,
+Pour rendre le tout agréable à utiliser, il faut que l’interface soit réactive : si l’on bouge un joueur,
il faut que les flèches qui y sont liés bougent aussi, il faut que les joueurs puissent bouger le long des flèches en mode visualiseur etc…
Le front-end de l’éditeur et du visualiseur étant assez ambitieux, et occupant une place importante du projet, nous avons décidés de l’effectuer en utilisant
le framework React qui rend simple le développement d’interfaces dynamiques, et d’utiliser typescript parce qu’ici on code bien et qu’on impose une type safety a notre code.
-
diff --git a/Documentation/Description.md b/Documentation/Description.md
index fee90c5..fecd0e0 100644
--- a/Documentation/Description.md
+++ b/Documentation/Description.md
@@ -1,6 +1,7 @@
# Welcome on the documentation's description
## Let's get started with the architecture diagram.
+

As you can see our entire application is build around three main package.
@@ -13,7 +14,7 @@ Allowing to operate on it.
The App now is more about the web application itself.
Having all the controllers of the MVC architecture the use the model, the validation system and the http system in the core.
-It also calls the twig's views inside of App. Finally, it uses the package Session. This one replace the $_SESSION we all know in PHP.
+It also calls the twig's views inside of App. Finally, it uses the package Session. This one replace the $\_SESSION we all know in PHP.
Thanks to this we have a way cleaner use of all session's data.
Nevertheless, all the controllers call not only twig views but also react ones.
Those are present in the package "front", dispatched in several other packages.
@@ -22,10 +23,11 @@ Such as assets having all the image and stuff, model containing all the data's s
Finally, we have the package "Api" that allows to share code and bind all the different third-hand application such as the web admin one.
## Main data class diagram.
+

You can see how our data is structured contained in the package "data" as explained right above.
-There is two clear part.
+There is two clear part.
First of all, the Tactic one.
We got a nice class named TacticInfo representing as it says the information about a tactic, nothing to discuss more about.
It associates an attribute of type "CourtType". This last is just an "evoluated" type of enum with some more features.
@@ -42,6 +44,7 @@ The last class we have is the Account. It could directly be incorporated in User
Then, Account only has a user and a token which is an identifier.
## Validation's class diagram
+

We implemented our own validation system, here it is!
@@ -50,32 +53,38 @@ In general, we use the implementation "SimpleFunctionValidator".
We reconize the strategy pattern. Indeed, we need a family of algorithms because we have many classes that only differ by the way they validate.
Futhermore, you may have notices the ComposedValidator that allows to chain several Validator.
We can see that this system uses the composite pattern
-The other part of the diagram is about the failure a specific field's validation.
+The other part of the diagram is about the failure a specific field's validation.
We have a concrete class to return a something more general. All the successors are just more precise about the failure.
## Http's class diagram
+

It were we centralize what the app can render, and what the api can receive.
-Then, we got the "basic" response (HttpResponse) that just render a HttpCodes.
+Then, we got the "basic" response (HttpResponse) that just render a HttpCodes.
We have two successors for now. ViewHttpResponse render not only a code but also a view, either react or twig ones.
Finally, we have the JsonHttpResponse that renders, as it's name says, some Json.
## Session's class diagram
+

-It encapsulates the PHP's array "$_SESSION". With two interfaces that dictate how a session should be handled, and same for a mutable one.
+It encapsulates the PHP's array "$\_SESSION". With two interfaces that dictate how a session should be handled, and same for a mutable one.
+
## Model View Controller
+
All class diagram, separated by their range of action, of the imposed MVC architecture.
All of them have a controller that validates entries with the validation system and check the permission the user has,and whether or not actually do the action.
These controllers are composed by a Model that handle the pure data and is the point of contact between these and the gateways.
Speaking of which, Gateways are composing Models. They use the connection class to access the database and send their query.
### Team
+

### Editor
+

### Authentification
-
+
diff --git a/Documentation/README.md b/Documentation/README.md
index 24c5472..6cc1eb2 100644
--- a/Documentation/README.md
+++ b/Documentation/README.md
@@ -1,3 +1,3 @@
-* [Description.md](Description.md)
-* [Conception.md](Conception.md)
-* [how-to-dev.md](how-to-dev.md)
\ No newline at end of file
+- [Description.md](Description.md)
+- [Conception.md](Conception.md)
+- [how-to-dev.md](how-to-dev.md)
diff --git a/Documentation/how-to-dev.md b/Documentation/how-to-dev.md
index 39435e6..287a7fe 100644
--- a/Documentation/how-to-dev.md
+++ b/Documentation/how-to-dev.md
@@ -3,17 +3,13 @@ machine, and how it works under the hood.
# How to run the project on my local computer
+1. Use phpstorm to run a local php server:
-1) Use phpstorm to run a local php server:
-* Go to configuration > add new configuration
-* Select "PHP Built-in Web Server", then enter options as follow:
-
- - port 8080
- - name the configuration "RunServer" to be more explicit
- - place the "Document Root" in `/public`
- - host is localhost
-* Click apply, OK
-* Now run it.
+- Go to configuration > add new configuration
+- Select "PHP Built-in Web Server", then enter options as follow:
+  - port 8080 - name the configuration "RunServer" to be more explicit - place the "Document Root" in `/public` - host is localhost
+- Click apply, OK
+- Now run it.
If you go to `http://localhost:8080` you'll see a blank page.
This is expected ! On your browser, open inspection tab (ctrl+shift+i) go to network and refresh the page.
@@ -39,12 +35,14 @@ Now refresh your page, you should now see all request being fulfilled and a form
Caution: **NEVER** directly connect on the `localhost:5173` node development server, always pass through the php (`localhost:8080`) server.
# How it works
-I'm glad you are interested in how that stuff works, it's a bit tricky, lets go.
+
+I'm glad you are interested in how that stuff works, it's a bit tricky, lets go.
If you look at our `index.php` (located in `/public` folder), you'll see that it define our routes, it uses an `AltoRouter` then delegates the request's action processing to a controller.
We can see that there are two registered routes, the `GET:/` (that then calls `SampleFormController#displayForm()`) and `POST:/result` (that calls `SampleFormController#displayResults()`).
-Implementation of those two methods are very simple: there is no verification to make nor model to control, thus they directly sends the view back to the client.
+Implementation of those two methods are very simple: there is no verification to make nor model to control, thus they directly sends the view back to the client.
here's the implementation of the `SampleFormController`
+
```php
require_once "react-display.php";
class SampleFormController {
@@ -63,7 +61,7 @@ As our views are now done using react (and defined under the `front/views` folde
If you look at the `send_react_front($viewURI, $viewArguments)` function, you'll see that is simply loads the file `src/react-display-file.php` with given arguments.
The file is a simple html5 template with a `
```
-here's how it renders if you do a request to `http://localhost:8080/`.
+here's how it renders if you do a request to `http://localhost:8080/`.

The index.php's router says that for a `GET` on the `/` url, we call the `SampleFormController#displayForm` method.
This method then uses the `send_react_front`, to render the `views/SampleForm.tsx` react element, with no arguments (an empty array).
-The view file **must export by default its react function component**.
+The view file **must export by default its react function component**.
## Server Profiles
-If you go on the staging server, you'll see that, for the exact same request equivalent, the generated `src/render-display-file` file changes :
+
+If you go on the staging server, you'll see that, for the exact same request equivalent, the generated `src/render-display-file` file changes :

(we can also see that much less files are downloaded than with our localhost aka development server).
Remember that react components and typescript files needs to be transpiled to javascript before being executable by a browser.
The generated file no longer requests the view to a `localhost:5173` or a `maxou.dev:5173` server,
-now our react components are directly served by the same server, as they have been pre-compiled by our CI (see `/ci/.drone.yml` and `/ci/build_react.msh`) into valid js files that can directly be send to the browser.
+now our react components are directly served by the same server, as they have been pre-compiled by our CI (see `/ci/.drone.yml` and `/ci/build_react.msh`) into valid js files that can directly be send to the browser.
If you go back to our `index.php` file, you'll see that it requires a `../config.php` file, if you open it,
-you'll see that it defines the `asset(string $uri)` function that is used by the `src/react-display-file.php`,
-in the `
-
+
+
+