This commit is contained in:
Denis Monnerat 2025-03-14 11:47:00 +01:00
parent 835598801e
commit 506ecfa837
9 changed files with 361 additions and 0 deletions

@ -15,5 +15,9 @@
#### Semaine 5
[API REST](cours/api.pdf), service firebase [tp5](./td_tp/tp5)
#### Semaine 6
[Nodejs](cours/nodejs.pdf) et api de données, [tp7](./td_tp/tp6)

Binary file not shown.

@ -0,0 +1,109 @@
# TP javascript : Nodejs
#### Configuration
À l'aide de la commande `npm`, installez le module `express` dont on aura besoin pour la suite.
npm install express
L'installation des modules se fait dans le repertoire `ǹode_modules`. C'est
là que `node` va les chercher par défaut.
Vous pouvez les installer à un autre endroit (option `--prefix` de `npm` et variable d'environnement
`ǸODE_PATH` pour `ǹode`)
Testez votre installation avec un serveur http minimaliste : `ǹode app.js`
```js
// app.js
const http = require('http');
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, () => {
console.log(`Server running at *:${port}/`);
});
```
#### Ex1
Un serveur web pour notre application todolist.
On va utiliser pour cela le module [express](https://expressjs.com/fr/4x/api.html). `express` facilite l'écriture
d'une application web en gérant notamment le routage et les entrées/sorties http.
```js
let express = require('express');
let app = express();
let todos = require('./todos.json')
app.use('/html',express.static('html'));
app.use('/css',express.static('css'));
app.use('/js',express.static('js'));
app.use('/img',express.static('img'));
app.use('/tags',express.static('tags'));
app.use(express.json())
```
- Notre serveur web possède une seule route : sa racine. Il renvoie le fichier `html/index.html`
- `app.use` permet d'enregistrer un middleware quelconque. Une fonction exécutée quand la route d'une requête
correspond à un path donné.
ici, on utlise le middleware interne `express.static` qui permet de servir du contenu statique. Pour notre application,
le contenu des repértoires `css`, `js`, `img` et `tags`.
L'application devrait accessible et utlisable à l'url `http://localhost:3000`. Testez.
On va mettre en oeuvre avec notre serveur nodejs une petite api rest pour gérer la todo-list
Le serveur maintiendra lui-même cette liste
```js
const todos = require('./todos.json')
```
une todo est représentée par la structure suivante :
```js
{ "id" : 1 , "title":"Avoid excessive caffeine","done":false }
```
On va ajouter au serveur les routes suivantes :
| route | méthode | action |
|---------- |:------------- |:------ |
| /todos | GET | renvoie la todo list (tableau) |
| /todos/:id | GET | renvoie la todo |
| /todos | POST | ajoute une todo, et renvoie le tableau |
| /todos | DELETE | efface un ensemble (tableau) de todo et renvoie la liste |
| /todos/:id | DELETE | efface une todo, et renvoie la liste |
| /todos/:id | PUT | modifie une todo, et renvoie la liste |
Les entrées/sorties de l'api seront formatées en JSON.
Voici l'implation de la première route :
```js
let todos = require('./todos.json')
app.use(express.json())
app.get('/todos', (req,res) => {
res.status(200).json(todos)
})
```
1. Implantez les autres routes,
2. Testez l'api avec CURL.
3. Branchez l'application avec cette api.

@ -0,0 +1,9 @@
p.todo {
display : flex;
justify-content : space-between;
}
.done {
text-decoration: line-through;
color: #ccc;
}

@ -0,0 +1,42 @@
<!doctype html>
<html>
<head>
<title>Riot todo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" integrity="sha512-Evv84Mr4kqVGRNSgIGL/F/aIDqQb7xQ2vcrdIwxfjThSH8CSR7PBEakCr51Ck+w+/U6swU2Im1vVX0SVk9ABhg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="todo.riot" type="riot"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/riot/9.4.4/riot+compiler.min.js" integrity="sha512-sMPQdAnmCCQmymthALQzoFXGFmG1hhiazFuC/8Y5hLentlAWNqs+eQQJJ/yeGC4DLk/JwLL3jGk6yoEEDNb+7w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://unpkg.com/@riotjs/route@9.2/index.umd.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link rel="stylesheet" href="todo.css">
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
>
</head>
<body>
<main class="container">
<todo></todo>
</main>
<script type="module">
import makeDataervice from "./js/api.js";
riot.register('router', route.Router);
riot.register('route', route.Route);
riot.compile().then(async () => {
let sa = makeDataervice();
riot.install(function(component){
component.serviceData = sa;
})
riot.mount('todo', {
title: 'I want to behave!',
todos: []
})
})
</script>
</body>
</html>

@ -0,0 +1,9 @@
export default function makeDataService(){
let url = 'votre url';
let service = {
// TODO
};
return service;
}

@ -0,0 +1,65 @@
let express = require('express');
let app = express();
let todos = require('./todos.json')
app.use('/html',express.static('html'));
app.use('/css',express.static('css'));
app.use('/js',express.static('js'));
app.use('/img',express.static('img'));
app.use('/tags',express.static('tags'));
app.use(express.json())
// Routes
//
app.get('/todos', (req,res) => {
res.status(200).json(todos)
})
app.get('/todos/:id', (req,res) => {
const id = parseInt(req.params.id)
// TODO
//
})
app.put('/todos/:id', (req,res) => {
const id = parseInt(req.params.id)
// TODO
//
})
app.post('/todos', (req,res) => {
let id = todos.length > 0 ? todos[todos.length - 1].id + 1 : 1
// TODO
//
})
app.delete('/todos/:id', (req,res) => {
const id = parseInt(req.params.id)
// TODO
//
})
app.delete('/todos', (req,res) => {
// TODO
//
})
app.listen( 3000,()=>{
console.log('listening on *:3000');
})

@ -0,0 +1,118 @@
<todo>
<router base = {base}>
<route path="(#)?/:filter?"
on-before-mount = { changeFilter }
on-before-update = { changeFilter }
>
<nav>
<ul>
<li>{this.state.todos.filter(todo => !todo.done).length} todos left</li>
</ul>
<ul>
<li each={filter in ['all','active','done']}>
<!--template if = {state.filter !== filter}-->
<a class={state.filter=== filter ? 'contrast':''} href="#/{filter}" > {filter.toUpperCase()}</a>
<!--template>
<template if = {state.filter === filter}>{filter.toUpperCase()}</template-->
</li>
</ul>
</nav>
<article>
<header>
<b>{props.title}</b>
</header>
<template each={ todo in filterTodos() } key = {todo.id}>
<p class="todo">
<label class={ todo.done ? 'completed' : null }>
<input role="switch"
type="checkbox"
checked={ todo.done }
onclick={ () => toggle(todo) } />
<span class = {todo.done ? 'done':''}> { todo.title } </span>
</label>
<a href="#" onclick={(e)=>remove(e,todo)}><i class="fa-solid fa-trash"></i></a>
</p>
<hr>
</template>
</article>
<form onsubmit={ add }>
<fieldset role="group">
<input type="text" oninput={ edit } />
<input type="button" disabled={ !state.text } value="Add #{ state.todos.length + 1 }">
<input class="contrast" type="button" disabled = { !state.todos.find ( e => e.done) } onclick={ clear } value="Clear done">
</fieldset>
</form>
</route>
</router>
<script>
export default {
base : 'http://localhost/~denis/RIOTJS/examples/todo-pico/',
changeFilter(r){
this.state.filter = r.params.filter || 'all'
},
async onBeforeMount(props, state) {
// initial state
this.state = {
todos: props.todos,
text: '',
filter:'all',
}
let todos = await this.serviceData.getTodos()
this.state.todos = todos;
this.update()
},
// listenTodos(todos){
// this.update({ todos : todos})
// },
filterTodos(){
if (this.state.filter === 'all')
return this.state.todos
if (this.state.filter === 'active')
return this.state.todos.filter(e=> !e.done)
if (this.state.filter === 'done')
return this.state.todos.filter(e=> e.done)
},
async remove(e,todo){
e.preventDefault()
let res = await this.serviceData.removeTodo(todo)
let todos = await this.serviceData.getTodos()
this.state.todos = todos
this.update()
},
edit(e) {
// update only the text state
this.update({
text: e.target.value
})
},
async clear(e) {
e.preventDefault()
// console.log(this.state.todos)
// let res = await this.serviceData.clearDone()
// this.state.todos = this.state.todos.filter(todo => !todo.done)
},
async add(e) {
e.preventDefault()
let text = this.state.text;
let res = await this.serviceData.addTodo({title : text , done : false})
let todos = await this.serviceData.getTodos()
this.state.todos = todos
this.update()
},
async toggle(todo) {
let res = await this.serviceData.toggleTodo(todo);
let todos = await this.serviceData.getTodos()
this.state.todos = todos
this.update()
}
}
</script>
</todo>

@ -0,0 +1,5 @@
[
{ "id":1,"title": "Avoid excessive caffeine", "done": false },
{ "id":2,"title": "Be less provocative", "done": true },
{ "id":3,"title": "Be nice to people", "done": true }
]