Skip to content
Snippets Groups Projects
Commit 37ffe8c2 authored by Matthias Desrumaux's avatar Matthias Desrumaux
Browse files

Add tp

parent 0e479248
No related branches found
No related tags found
No related merge requests found
Showing
with 2375 additions and 0 deletions
# Express TP: Liste des tâches
Le but de ce tp est de créer une application pour réaliser la gestion de liste de tâche.
Cette application devra répondre au critére suivant :
- Je peux crée / consulter / supprimer une liste de tâche
- Je peux crée / consulter / éditer une tâche
- Je peux supprimer une tâche si elle n'est associé à aucune liste de tâche
- Depuis un guide je peux visualiser les tâches et avoir un lien pour consulter leurs détails.
Vous devrez crée de zéro les fichiers `TaskListRouter` et `TaskRouter`.
## Installation des dépendances
Les paquets utilisé pour ce tp doivent être installer via la commande suivante.
```bash
npm install
```
## Executer le tp
Il est nécessaire d'utiliser la commande ci-dessous car l'architecture des sources de l'application n'est pas la même.
Node cherche toujours le dossier node_modules la ou la commande `node` est executer.
```bash
npm start
```
## Etape 1: Création des routers
Dans cette premiére partie, le but est de créer les différents routers de notre application.
Ils devront répondre au routes suivantes, attention les routes contenant des id devront être variabiliser pour convenir peut importe la valeur :
TaskRouter
- `/task/`
GET doit afficher toutes les tâches
- `/task/display/0`
GET doit afficher la tache 0
- `/task/edit/0`
GET affiche un formulaire pour éditer la tache 0.
POST applique les changements sur la tâche 0
- `/task/delete/0`
POST supprime la tâche 0
- `/task/new`
GET affiche un formulaire pour l'ajout d'une tâche
POST crée la nouvelle tâche
TaskListRouter
- `/list/`
GET doit afficher toutes les listes de tâches
- `/list/0`
GET doit afficher les tâches de liste 0
- `/list/0/edit`
GET affiche un formulaire pour éditer la liste 0.
POST applique les changements sur la liste 0
- `/list/0/delete`
POST supprime la liste 0
- `/list/new`
GET affiche un formulaire pour l'ajout d'une liste
POST crée une nouvelle liste
## Etape 2: Filtrer les requêtes
Dans les cas comme `/task/edit/0` on souhaiterait avant d'éxecuter la méthode principale récupérer la tâche avant.
Vous devrez crée un middleware à éxecuter avant le c'est route. Si il parvient à trouver la tâche alors il doit l'ajouter à la requête puis continuer l'éxecution.
Si elle est manquante alors il doit intérrompre l'éxecution et retourner erreur avec le code 404.
Vous devrez alors dans votre handler principal avoir `request.task` qui doit être défini et non null.
Faire de même avec les listes de tâches.
## Etape 3: Afficher les données
Express peut être étendu avec de nombreux moteur de template. Ici nous utiliseront pug. Vous devrez créer les différentes pages correspondantes et les appellé aux bonnes routes. Le but ici n'est pas faire de copier coller mais d'utiliser les fonctionnalité de pug pour facilité l'écriture de celle-ci.
## Etape 4: Récupération d'un formulaire
Comme à l'étape 2 crée un middelware permettant de récupérer le formulaire et de le passer à la requête suivante.
Pour `/task/edit/0` en post vous devrez pouvoir éxecuter vos 2 middelware. Il suiffera dans le handler principal d'appliquer les modifications.
## Pour aller plus loin
La plus part des entreprises vous demanderont de tester votre application.
C'est la que `mocha`, `chai` et `chai-http`.
Vous avez un exemple de test crée dans le dossier test.
Le but ici serait de tester le comportement de notre application.
```bash
npm test
```
\ No newline at end of file
This diff is collapsed.
{
"name": "express-training",
"version": "1.0.0",
"description": "A small trainning on express library & node.js for IFI curses",
"main": "index.js",
"scripts": {
"test": "mocha test/check.js",
"start": "node src/main.js"
},
"keywords": [
"NODE.JS",
"EXPRESS",
"JS"
],
"author": "Desrumaux, Solowieff, Quentin",
"license": "ISC",
"dependencies": {
"express": "^4.17.1"
},
"devDependencies": {
"mocha": "^6.2.1"
}
}
class Registry {
/**
* Build a new registry
*/
constructor(){
this.container = [];
}
/**
* Find an item of the registry
*
* @param {Number | Function} seeker is the criterium to find an item of the registry
*
* @returns an item from the registry or null if missing
*/
find( seeker ){
let seekerUnited;
if( seeker instanceof Function ){
seekerUnited = seeker;
} else {
seekerUnited = (id) => id === seeker;
}
for ( let index = 0; index < this.container.length; index++ )
if ( seekerUnited( index, this.container[ index ] ) ){
return {
id: index,
item: this.container[ index ]
};
}
return null;
}
/**
* Get the item id or null if the item missing
*
* @param {Type} item is the item seeked
*
* @returns the id of the item
*/
findId( item ){
for ( let index = 0; index < this.container.length; index++ )
if ( item === this.container[ index ] ){
return index;
}
return null;
}
/**
* Add a new item to the registry
*
* @param {Type} item is the new task to be added
*
* @returns the id of the item
*/
insert( item ){
return this.findId( item ) || (
this.container.push( item ) - 1
);
}
delete( id ){
let [item] = this.container.splice( id, 1 );
return item;
}
all(){
let list = [];
for ( let index = 0; index < this.container.length; index++ ){
list.push({
id: index,
item: this.container[ index ]
});
}
return list;
}
}
const TaskRegistry = new Registry();
exports.TaskRegistry = TaskRegistry;
const TaskListRegistry = new Registry();
exports.TaskListRegistry = TaskListRegistry;
\ No newline at end of file
module.exports.Task = class {
/**
* Create a task with a simple name
*
* @param {String} name is the task name
* @param {String} description is a small text to give more detail about the task
* @param {Number} start is the date from since the task start
* @param {Number} duetime is the date where the task sould be complete
*/
constructor( name, description = "", start = null, duetime = null ){
this.name = name;
this.description = description;
this.start = start;
this.duetime = duetime;
}
/**
* @returns the task has been started
*/
isStarted(){
if( this.start ){
return this.start < Date.now();
}
return false;
}
/**
* @returns if the task is finished
*/
isFinished(){
if( this.duetime ){
return this.duetime < Date.now();
}
return false;
}
/**
* @returns {String} a small description of this task
*/
toString(){
let format = (dateInMillis) => {
let date = new Date( dateInMillis );
return `${ date.getDay() }/${ date.getMonth() }/${ date.getFullYear() }`;
};
let date = "";
if( this.start && this.duetime ){
date = `${ format( this.start ) } -> ${ format( this.duetime ) }`
} else if( this.start ) {
date = `${ format( this.start ) } -> no due date`;
} else if( this.duetime ){
date = `due to ${ format( this.duetime ) }`;
}
return `${ this.name }: ${date}\n${this.description}`;
}
}
\ No newline at end of file
/**
* Sort a task by their start time and their due time
*
* @param {Task} taskA is the first one
* @param {Task} taskB is the second one
*
* @returns {Number} taskA is before {-1} or after {1} taskB
*/
function defaultCriterium( taskA, taskB ){
if( taskA.start && taskB.start ){
return taskA.start - taskB.start;
} else if( taskA.start ){
return -1;
} else if( taskB.start ){
return 1;
}
if( taskA.duetime && taskB.duetime ){
return taskA.duetime - taskB.duetime;
} else if( taskA.duetime ){
return -1;
} else if( taskB.duetime ){
return 1;
}
return 0;
}
module.exports.TaskList = class {
/**
* Create a task list
*
* @param {String} name is the task list name
* @param {Number[]} list is the default task for the task list
*/
constructor( name, list = [] ){
this.name = name;
this.list = list;
}
/**
* @returns true if the task has zero task
*/
isEmpty(){
return this.list.length === 0;
}
/**
* Add a task to the list
*
* @param {Number} taskId
*/
add( taskId ){
this.list.push( taskId );
}
/**
* Delete some task from the task list
*
* @param {Function} mustBeDeleted is the function who determine which task we should keep
*/
removeIf( mustBeDeleted ) {
let keepIt = [];
this.list.forEach((element) => {
if( ! mustBeDeleted( element ) ){
keepIt.push( element );
}
});
this.list = keepIt;
}
/**
* Remove a task from the TaskList
*
* @param {Number} taskId is the task toitem.toString()be deleted
*/
remove( taskId ){
this.removeIf( (anotherTask) => taskId == anotherTask );
}
/**
* Sort the task list
*
* @param {Function} criterium is the criterium to determine the order of the list
* @param {Boolean} duplicate determine if we should create a new task list or not
*
* @returns {TaskList} only when duplicate is true, create a new task list from the sorted list
*/
sort( criterium = defaultCriterium, duplicate = false ){
let sortedTask = this.task.sort( criterium );
if( duplicate ){
return new TaskList( sortedTask );
} else {
this.list = sortedTask;
}
return null;
}
/**
* @returns {String} print the task list
*/
toString(){
let print = `Liste des taches "${ this.name }"`;
return print;
}
/**
* Contains this task id
*
* @param {Number} id is the task id
*/
has( id ){
for (const _id of this.list) {
if( id === _id ){
return true;
}
}
return false;
}
};
\ No newline at end of file
const express = require( "express" );
const app = express();
module.exports = function( hdl ){
const bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.set('view engine', 'pug');
app.set('views', `${ __dirname }/web` );
const TaskListRouter = require( "./TaskListRouter" );
app.use( "/list", TaskListRouter );
const TaskRouter = require( "./TaskRouter" );
app.use( "/task", TaskRouter );
hdl( app );
};
\ No newline at end of file
const init = require( "./init" );
init( app => {
app.listen( 8080 );
});
\ No newline at end of file
File moved
html
body
form(action=target, method="post")
p Nom de la liste des tâches
input(type="text", name="name")
table
th
td
td Nom de la tâche
each task in tasks
tr
td
if selected( task.id )
input(type="checkbox", name="task", value=task.id, checked="checked")
else
input(type="checkbox", name="task", value=task.id )
td #{ task.item.name }
button(type="submit") Validez
\ No newline at end of file
html
body
table
th
td Liste de tâches
td Actions
each tasklist in list
tr
td #{ tasklist.item.name }
td
a(href=`/list/${ tasklist.id }`) détail
form(action=`/list/delete/${ tasklist.id }`, method="post")
button(type="submit") supprimer
a(href=`/list/new`) ajouter une nouvelle liste de tâche
html
body
h1 #{ tasklist.value.name }
table
th
td Nom de la tâche
td Actions
each task in tasks
tr
td #{ task.item.name }
td
a(href=`/task/${ task.id }`) détail
a(href=`/list/${ tasklist.id }/edit`) Editer la liste
html
body
table
th
td Identifiant de la tache
td Nom
td Description
td Action
each task in list
tr
td #{ task.id }
td #{ task.item.name }
td #{ task.item.description }
td
a(href=`/task/display/${ task.id }`) Afficher
a(href=`/task/edit/${ task.id }`) Editer
a(href=`/task/delete/${ task.id }`) Supprimer
a( href="/task/new" ) Crée une nouvelle tâche
\ No newline at end of file
html
body
form(action=target, method="post")
p Nom de la tâche
input(type="text", name="name", value= task ? task.name : "" )
p Description
input(type="text", name="description", value= task ? task.description : "")
p Début de la tache
input(type="date", name="start", value= task && task.start ? task.start : "")
p Fin de la tache
input(type="date", name="duetime", value= task && task.duetime ? task.duetime : "")
button(type="submit") valider
\ No newline at end of file
const chai = require( "chai" );
const chai_http = require( "chai-http" );
const init = require( "../src/init" );
chai.use( chai_http );
init( app => {
app.listen( 8080, () => {
describe( "Express TP TaskList", () => {
it( "request has answer", (done) => {
chai.request( "http://127.0.0.1" )
.get( "/" )
.end(( err, res ) => {
res.should.have.status( 200 );
done();
});
});
});
});
});
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment