:: Enseignements :: ESIPE :: E3INFO :: 2023-2024 :: Programmation Web avec JavaScript ::
[LOGO]

TP noté d'Application Web 2 - session 1


Le but de ce TP est de réaliser une application de suivi de tache, où l'on peut créer une nouvelle tâche, éditer une tâche, supprimer une tâche et trier la liste des tâches.

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éer dans ce répertoire seront sauvegarder. 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 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 - Tasker

Dans un premier temps, nous allons récupérer un tar.gz qui contient la commande esbuild et les bibliothèques react et react-dom, le tout dans un répertoire tasker.
Décompresser l'archive (tar zxvf tasker-node-modules.tgz) tasker-modules.tgz dans le répertoire EXAM.
Rappel, pour transformer le fichier JSX en JS, on utilise la commande
        ./node_modules/.bin/esbuild tasker.jsx --bundle --outfile=tasker.js
    

Pour démarrer, on va utiliser le fichier tasker.html suivant
        <!DOCTYPE html>
        <html>
            <head>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <link rel="icon" href="data:;base64,=">
                <script src="tasker.js" type="text/javascript"></script>
                <style>
                  * {
                    box-sizing: border-box;
                  }

                  .tasklist {
                    display: flex;
                    flex-flow: row wrap;
                  }

                  .task {
                    flex: 100px;
                    padding: 8px;
                    margin: 8px;
                    background: silver;

                    display: flex;
                    flex-direction: row;
                  }

                  .taskleft {
                    flex: 1;
                    align-items: center;
                    justify-content: space-around;
                    min-width: 175px;
                    padding: 5px;
                    margin: 5px;
                    background: gold;
                  }

                  .tasktitle {
                    margin: 4px 0px 10px 0px;
                    font-weight: bold;
                  }

                  .taskright {
                    flex: 2;
                    padding: 5px;
                    margin: 5px;
                    background: lightblue;
                  }

                  .taskright textarea {
                    width: 100%;
                    height: 100%;
                    min-width: 250px;
                  }
                </style>
            </head>
            <body>
                <div id="App"></div>
            </body>
        </html>
    

Et pour le fichier tasker.jsx suivant
     import * as React from 'react';
     import * as ReactDOM from 'react-dom/client';

     function App() {
       let tasks = [
         { id: "1", title: "Upcoming campaign", author: "Jane", tags : ["marketing"], text: "Call John"},
         { id: "2", title: "Approve use of ChatGPT", author: "Sama", tags : ["legal", "hr"], text: "Are we in trouble ?"},
         { id: "3", title: "New Design !", author:"Jean", tags: ["marketing"], text: "What do you think about the new design ?"}
       ];
       return <>
          <h1>Tasker</h1>
        </>;
     }

     window.onload = () => {
       let appDOM = document.getElementById("App");
       let root = ReactDOM.createRoot(appDOM);
       root.render(<App/>);
     };

    

On utilisera de plus le serveur Java JExpress.java pour servir les fichiers tasker.html et tasker.js et l'API REST spécifique aux tâches.

  1. 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/tasker.html.
  2. A partir de maintenant, on va modifier le fichier tasker.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.
    Créer les composants TaskList et TaskItem qui permettent d'afficher les tâches qui sont définies dans le tableau en dure task (dans la fonction App).
    Pour trouver la structure exacte, utiliser l'image de l'arbre DOM et de l'application ci-dessus. Vous pouvez noter que les fonds (background) des classes CSS ont des couleurs différentes ce qui vous permet de confirmer visuellement qui est qui.
    Écrire les composants TaskList et TaskItem et visualiser que l'affichage est correcte.
    Note: pour l'instant, on ne s'occupe ni des boutons, ni du sélecteur.

  3. On veut maintenant afficher les tâches gérées par le serveur. Pour cela, le serveur possède la route suivante
          GET /api/task
        
    qui renvoie au format JSON la liste des tâches stockées dans le serveur.
    En utilisant la fonction fetch, modifier votre code pour afficher les tâches renvoyées par le serveur.

  4. On souhaite ajouter un bouton "X" qui permet de supprimer une tâche sur le serveur. Pour cela, le serveur possède la route suivante
          DELETE /api/task/id
         
    Avec "id", l'id de la tâche que l'on veut supprimer.
    Une fois la tâche supprimée, il vous faut mettre à jour l'affichage.

  5. On souhaite maintenant que l'affichage des tâches se fasse en fonction des titres (title). On va pour cela, utiliser une nouvelle route GET
           GET /api/task/key
         
    qui prend dernier composant de l'URI la clef key (qui a pour valeur id, title, author, etc). La clef est utilisée pour renvoyer un texte au format JSON trié par cette clef.
    Modifier votre code pour déclarer sous forme de const dans la fonction App la valeur de la clef (ici, title) et modifier votre code pour utiliser la nouvelle route.
    Attention à ce que lorsque l'on supprime une tâche, les autres tâches restent triées avec la clé.

  6. Normalement, depuis la première question, vous avez un beau warning de React qui vous dit que le texte n'est pas éditable. On va faire en sorte que cela marche. Pour cela, il existe une route
            PUT /api/task/id
          
    qui prend en paramètre une tâche au format JSON et modifie les valeurs de celle-ci. Note: cette route modifie toutes les valeurs, si vous voulez modifier que le texte, il faut quand même envoyer les autres propriétés que vous ne souhaitez pas modifier.
    Comme on veut faire envoyer la nouvelle tâche au format JSON, le fetch doit spécifier que l'on envoie du JSON et que l'on souhaite recevoir du JSON dans l'entête de la requête HTTP et que le contenu de la requête est une chaine de caractères encodée au format JSON.
            fetch("/api/task/12", {
              method: "PUT",
              headers: {
                'Content-Type': 'application/json',   // je t'envoies du JSON
                'Accept': 'application/json'          // je veux recevoir du JSON
              },
              body: JSON.stringify(task)});
          
    Ici, pour une tâche qui a pour id 12.

  7. On souhaite ajouter un sélecteur (cf. l'image de l'application) permettant de choisir la clé utilisée pour trier. Pour cela, on va utiliser la balise HTML select qui s'utilise comme cela en React:
            <select defaultValue="TODO" onChange="TODO">
              <option value="id">id</option>
              <option value="title">title</option>
              <option value="author">author</option>
            </select>
          

    Modifier votre code pour que l'utilisateur puisse changer la clé utiliser pour trier les tâches.

  8. Enfin pour les plus balèzes, on souhaite pouvoir ajouter une nouvelle tâche en utilisant le bouton "+" (cf. l'image de l'application). Regarder dans le code de JExpress.java quelle est la route nécessaire et comment il faut faire pour créer une nouvelle tâche puis modifier le fichier JSX pour ajouter le bouton.