:: Enseignements :: ESIPE :: E3INFO :: 2025-2026 :: Web et Géomatique ::
![[LOGO]](http://monge.univ-eiffel.fr/ens/resources/mlv.png) |
TP noté d'Application Web - session 1
|
Le but de ce TP est de réaliser une application qui affiche des informations sur des pays,
un "Country Explorer".
Vous devez créer vos fichiers dans le répertoire EXAM qui est un sous répertoire de votre
répertoire home dans l'environnement de TP noté. Seuls les fichiers créés dans ce répertoire
seront sauvegardés. Donc si vous ne créez pas les fichiers dans le répertoire EXAM
mais dans un autre répertoire, ils ne seront pas sauvegardés, donc pas corrigés.
Comme l'environnement coupe les communications TCP vers l'extérieur,
Il est important de faire attention à la qualité du code que vous allez rendre.
Avoir un code qui semble marcher, mais qui n'est pas maintenable, pas compréhensible ou
qui contient du code mort (qui ne sert à rien) sera fortement pénalisé.
Voilà une idée graphique de l'application que l'on veut réaliser
Et voilà l'arbre DOM que l'on souhaite obtenir.
Exercice 1 - Country Explorer
Dans un premier temps, récupérer le
tar.gz qui contient la commande
esbuild
et les bibliothèques
react et
react-dom.
Décompresser l'archive (
tar zxvf country-node-modules.tgz)
country-node-modules.tgz
dans le répertoire
EXAM.
Rappel, pour transformer le fichier JSX en JS, on utilise la commande
./node_modules/.bin/esbuild country.jsx --bundle --outfile=country.js
L'API presque REST du serveur est définie comme ceci:
-
GET /api/country renvoie un tableau d'objets contenant le nom du pays, sa capitale et sa monnaie
Vous pouvez tester en copiant dans votre navigateur http://localhost:8080/api/country.
-
GET /api/flag/name renvoie le drapeau d'un pays en fonction de son nom.
Le name est le nom du pays (par ex: france) que vous devez passer dans l'URI.
La valeur de retour est un objet JSON contenant le nom du pays et le drapeau sous forme d'émoji.
Vous pouvez tester en copiant dans votre navigateur http://localhost:8080/api/flag/france.
Cet appel renvoie un code 200 si cela s'est bien passé, 404 si le pays n'a pas été trouvé.
-
DELETE /api/country permet de supprimer un pays.
Le nom du pays est envoyé sous forme d'un objet JSON ayant une propriété countryName,
par ex: { "countryName" : "france" }
Cet appel renvoie un code 200 si cela s'est bien passé, 404 si le pays n'a pas été trouvé.
-
POST /api/country permet de créer/mettre à jour un pays.
Les informations du pays sont envoyées sous forme d'un objet JSON contenant les champs
name et capital (et optionnellement, les champs currency et flag).
Cet appel renvoie un code 201 si un nouveau pays a été créé,
200 si un pays existant a été mis à jour.
Attention : l'API ne suit pas les recommandations REST, juste pour voir si vous êtes capables de vous adapter !
Pour démarrer, on va utiliser le fichier
country.html suivant
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="icon" href="data:,">
<script src="country.js" type="text/javascript"></script>
<style>
* {
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: #fafafa;
margin: 0;
padding: 20px;
}
h1 {
text-align: center;
}
.container {
max-width: 1000px;
margin: auto;
}
.card {
background: white;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
box-shadow: 0 2px 4px rgba(0,0,0,.1);
}
.country-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 12px;
}
.flag {
font-size: 3rem;
}
input {
width: 100%;
padding: 10px;
margin-bottom: 10px;
}
button {
padding: 10px 14px;
cursor: pointer;
border: none;
border-radius: 4px;
}
.primary {
background: #1976d2;
color: white;
}
.danger {
background: #d32f2f;
color: white;
}
.form-row {
display: flex;
gap: 10px;
margin-bottom: 10px;
}
.form-row input {
margin-bottom: 0;
}
.error {
color: #d32f2f;
margin: 10px 0;
}
</style>
</head>
<body>
<div id="App"></div>
</body>
</html>
Et pour le fichier
country.jsx suivant
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
function App() {
return <h1>TODO !</h1>;
}
window.onload = () => {
const appDOM = document.getElementById("App");
const root = ReactDOM.createRoot(appDOM);
root.render(<App/>);
};
On utilisera de plus le serveur Java
JExpress.java
pour servir les fichiers
country.html et
country.js et l'API REST spécifiée ci-dessus.
L'application est composée de 3 parties:
-
la partie haute qui permet d'ajouter un nouveau pays
ou de mettre à jour les informations d'un pays existant.
-
La partie centrale, qui est une barre de recherche qui permet de filtrer les cartes des pays à afficher.
Le filtrage se fait côté client, pas côté serveur.
-
La partie basse, qui contient les cartes (card) de chaque pays sur une grille.
En termes de développement, on va d'abord développer la partie basse, puis la partie centrale,
puis enfin la partie haute.
-
Utiliser esbuild pour réécrire le fichier JSX en fichier JS puis
lancer le serveur java JExpress.java dans le répertoire courant et
vérifier avec un navigateur que l'application s'affiche bien à l'adresse
http://localhost:8080/country.html.
-
A partir de maintenant, on va modifier le fichier country.jsx pour créer notre application,
et il ne faudra pas oublier après chaque modification de relancer esbuild
ou alors, vous pouvez utiliser l'option --watch.
Dans un premier temps, on va développer les composants App et CountryCard.
Le composant App contient le tableau des pays. Le composant CountryCard
est responsable de l'affichage d'un pays.
Pour récupérer les pays, faites un appel asynchrone à l'API dans un useEffect.
L'API renvoie le nom des pays et des capitales en minuscule, on utilisera la fonction ci-dessous
pour afficher la première lettre en majuscule.
function capitalizeFirstLetter(string) {
if (!string) {
return "";
}
return string.charAt(0).toUpperCase() + string.slice(1);
}
Pour trouver la structure exacte, utiliser l'image de l'arbre DOM et de l'application ci-dessus.
Écrire les composants App et CountryCard et visualiser que l'affichage est correct.
Note : pour l'instant, on ne s'occupe ni des drapeaux ni des boutons "Delete".
Note2 : si React vous engueule sur la console du navigateur web, il faut faire quelque chose !
-
On souhaite ajouter l'affichage des drapeaux sachant que ceux-ci sont accessibles
par un autre appel à l'API.
Si un drapeau n'est pas disponible, au lieu d'afficher un message d'erreur dans la console,
on utilisera l'émoji suivant: "🏳️".
Mettre à jour le code pour que les drapeaux s'affichent.
-
On souhaite maintenant pouvoir filtrer graphiquement les cartes (cards) des pays
que l'on affiche.
Changer l'affichage graphique pour utiliser un input pour que l'utilisateur
puisse taper son filtre.
On va afficher uniquement les cartes des pays commençant par le texte entré par l'utilisateur.
(utiliser startsWith sur string).
Si aucun texte n'est entré, toutes les cartes doivent être affichées.
Créer le composant CountrySearch pour cela.
-
On souhaite maintenant que le bouton "Delete" sur les cartes des pays marche.
Comment allez-vous procéder ?
Faites les changements qui s'imposent sachant qu'une fois le pays supprimé,
vous devez afficher les pays restants en faisant une demande au serveur.
-
On veut que si le serveur a un problème lors du chargement des pays,
le message "Failed to fetch countries" soit affiché graphiquement (en rouge, cf. le CSS)
juste au-dessus de la grille des pays.
Modifier votre code en conséquence.
Note: pour tester, au niveau du code du serveur Java, chercher un
if (false) { et remplacer le false par true.
-
On veut maintenant ajouter la première partie de l'interface graphique,
celle qui permet d'ajouter un nouveau pays.
Dans un premier temps, implanter cette feature en utilisant un FormData
(cf. la partie du cours sur le DOM).
L'idée est de s'enregistrer (avec onSubmit) au niveau du formulaire,
pour récupérer les valeurs de tous les inputs puis de les envoyer au serveur.
Faites les changements qui s'imposent.
-
Si vous ne l'avez pas déjà fait, une fois que l'on a cliqué sur le bouton pour créer ou mettre à jour
un pays, on veut que les inputs se réinitialisent à leur valeur par défaut.
Note: il y a plusieurs façons de faire, essayer de faire simple et pas bourrin (SVP) !
-
Enfin, au niveau du filtre, on aimerait bien que dans un premier temps, lorsque l'utilisateur tape
quelque chose, que les pays dont le nom commence par le filtre aient leurs noms
(exactement la partie de leurs noms qui correspond au filtre)
surlignée en jaune (#fbc02d).
Puis 300 ms plus tard, que les cartes non filtrées disparaissent (utiliser un timeout pour cela),
à ce moment-là, les noms ne sont plus en jaune.
Si pendant les 300 ms, l'utilisateur tape une nouvelle lettre, alors cela doit annuler l'animation
et une nouvelle animation doit être planifiée dans 300 ms, sinon, cela va clignoter !
Implanter ce comportement.
© Université de Marne-la-Vallée