todo riot, avec router
This commit is contained in:
@@ -105,6 +105,5 @@ Le modèle utilise PDO, en php. Il vous faudra créér une table avec les attrib
|
||||
1. Complétez le fichier index.php
|
||||
2. Testez votre api à la ligne de commandes en utilisant `curl`.
|
||||
3. Connectez votre application todolist avec l'api.
|
||||
|
||||
Écrivez un module "abstrait" en javascript pour l'interaction
|
||||
avec l'api. Ce module devra pouvoir être changer pour utiliser firebase **sans que l'application cliente ne change**.
|
||||
4. Connectez votre api à l'application [todo](./src/todo-riot). Il faut
|
||||
complétez le fichier api.js. Prenez soin de modifier le fichier `htaccess`.
|
||||
|
||||
74
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/app.riot
Normal file
74
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/app.riot
Normal file
@@ -0,0 +1,74 @@
|
||||
<app>
|
||||
<router base = {base}>
|
||||
<route path="/:filter?"
|
||||
on-before-mount = { changeFilter }
|
||||
on-before-update = { changeFilter }
|
||||
>
|
||||
|
||||
<h1>To Do List</h1>
|
||||
|
||||
<todo-form
|
||||
add = { add } />
|
||||
|
||||
<todo-nav
|
||||
selection = {state.filter}
|
||||
left = {this.state.todos.filter(todo => !todo.done).length} />
|
||||
|
||||
<todo-list
|
||||
todos = { filterTodos() }
|
||||
toggle = { toggle }
|
||||
remove = { remove } />
|
||||
|
||||
</route>
|
||||
</router>
|
||||
<script>
|
||||
export default {
|
||||
base : '/~denis/web_2024/tp5/todo-riot/', // Votre URL
|
||||
state : {
|
||||
todos : [],
|
||||
filter : 'all'
|
||||
},
|
||||
changeFilter(r){
|
||||
this.state.filter = r.params.filter || 'all'
|
||||
},
|
||||
|
||||
async onBeforeMount(props, state) {
|
||||
let todos = await this.serviceData.getTodos()
|
||||
this.state.todos = todos;
|
||||
this.update()
|
||||
},
|
||||
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()
|
||||
},
|
||||
|
||||
async add(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>
|
||||
</app>
|
||||
16
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/css/todo.css
Normal file
16
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/css/todo.css
Normal file
@@ -0,0 +1,16 @@
|
||||
p.todo {
|
||||
display : flex;
|
||||
justify-content : space-between;
|
||||
}
|
||||
|
||||
.done {
|
||||
text-decoration: line-through;
|
||||
color: #ccc;
|
||||
}
|
||||
.is-active {
|
||||
color : #8EB901;
|
||||
}
|
||||
.delete {
|
||||
background-color :#9B2318;
|
||||
}
|
||||
|
||||
8
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/htaccess
Normal file
8
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/htaccess
Normal file
@@ -0,0 +1,8 @@
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteBase /~denis/web_2024/tp5/todo-riot/ # votre url
|
||||
RewriteRule ^index\.html$ - [L]
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule . index.html [L]
|
||||
</IfModule>
|
||||
56
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/index.html
Normal file
56
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/index.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<!doctype html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Riot todo</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<base href="/~denis/web_2024/tp5/todo-riot/">
|
||||
|
||||
<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="https://cdn.jsdelivr.net/npm/riot@10.0.0/riot+compiler.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@riotjs/route@10.0.0/index.umd.js"></script>
|
||||
|
||||
|
||||
<link rel="stylesheet" href="css/todo.css">
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css"
|
||||
>
|
||||
<!-- composants riot -->
|
||||
|
||||
<script src="app.riot" type="riot"></script>
|
||||
<script src="todo-list.riot" type="riot"></script>
|
||||
<script src="todo-nav.riot" type="riot"></script>
|
||||
<script src="todo-form.riot" type="riot"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main class="container">
|
||||
<app />
|
||||
</main>
|
||||
|
||||
<script type="module">
|
||||
|
||||
import makeDataService from "./js/api.js";
|
||||
|
||||
riot.register('router', route.Router);
|
||||
riot.register('route', route.Route);
|
||||
|
||||
riot.compile().then(async () => {
|
||||
|
||||
let sa = makeDataService();
|
||||
|
||||
riot.install(function(component){
|
||||
if (component.name === "app")
|
||||
component.serviceData = sa;
|
||||
})
|
||||
|
||||
|
||||
riot.mount('app')
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
45
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/js/api.js
Normal file
45
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/js/api.js
Normal file
@@ -0,0 +1,45 @@
|
||||
export default function makeDataService(){
|
||||
let url = 'http://localhost/~denis/web_2024/tp5/api_php/todo/'
|
||||
let service = {
|
||||
getTodos : getTodos,
|
||||
addTodo : addTodo,
|
||||
removeTodo : removeTodo,
|
||||
toggleTodo : toggleTodo,
|
||||
};
|
||||
|
||||
async function getTodos()
|
||||
{
|
||||
let res = await fetch(url,{
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
})
|
||||
;
|
||||
let json = await res.json();
|
||||
return json.results;
|
||||
|
||||
|
||||
}
|
||||
async function addTodo(todo)
|
||||
{
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
method: "POST",
|
||||
body: JSON.stringify(todo)
|
||||
});
|
||||
}
|
||||
async function removeTodo(todo)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
async function toggleTodo(todo)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
return service;
|
||||
}
|
||||
31
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/todo-form.riot
Normal file
31
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/todo-form.riot
Normal file
@@ -0,0 +1,31 @@
|
||||
<todo-form>
|
||||
<form onsubmit = { add }>
|
||||
<fieldset role="group">
|
||||
<input type="text" placeholder="Buy milk and eggs..." oninput = { edit }>
|
||||
<button disabled = { !state.text } ><i class="fas fa-plus"></i></button>
|
||||
</fieldset>
|
||||
</form>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
state : {
|
||||
text:''
|
||||
},
|
||||
|
||||
edit(e) {
|
||||
// update only the text state
|
||||
this.state.text = e.target.value
|
||||
this.update()
|
||||
},
|
||||
add(e) {
|
||||
e.preventDefault()
|
||||
this.props.add(this.state.text);
|
||||
},
|
||||
clear(e){
|
||||
e.preventDefault();
|
||||
this.props.clear()
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
</todo-form>
|
||||
17
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/todo-list.riot
Normal file
17
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/todo-list.riot
Normal file
@@ -0,0 +1,17 @@
|
||||
<todo-list>
|
||||
<article>
|
||||
<div each={ todo in props.todos } key={todo.id}>
|
||||
<p class="todo">
|
||||
<label class={ todo.done ? 'completed' : null }>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={ todo.done }
|
||||
onclick={ () => props.toggle(todo) } />
|
||||
<span class = {todo.done ? 'done':''}> { todo.title } </span>
|
||||
</label>
|
||||
<a href="#" onclick={(e)=>props.remove(e,todo)}><i class="fa-solid fa-trash"></i></a>
|
||||
</p>
|
||||
<hr>
|
||||
</div>
|
||||
</article>
|
||||
</todo-list>
|
||||
12
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/todo-nav.riot
Normal file
12
R4.01_R4.A.10/td_tp/tp6/src/todo-riot/todo-nav.riot
Normal file
@@ -0,0 +1,12 @@
|
||||
<todo-nav>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a class={props.selection === 'active'?'is-active':null} href="active"><i class="far fa-circle"></i></a></li>
|
||||
<li><a class={props.selection === 'done'?'is-active':null} href="done"><i class="fas fa-circle"></i></a></li>
|
||||
<li><a class={props.selection === 'all'?'is-active':null} href="all"><i class="fas fa-adjust"></i></a></li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>{props.left} todos left</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</todo-nav>
|
||||
Reference in New Issue
Block a user