Skip to content
Snippets Groups Projects
Commit 266d4311 authored by Camille PILLOT's avatar Camille PILLOT
Browse files

Merge branch 'feat/avis' into 'main'

feat: add avis page with navigation

See merge request !2
parents 3e819a94 2901a67e
No related branches found
No related tags found
1 merge request!2feat: add avis page with navigation
Pipeline #66285 skipped
# Création du composant avis
***On est parti pour créer une nouvelle page !***
Elle servira à afficher les avis existants de la base de donnée. Et elle devrait ressembler à [ceci](https://allocine.takima.dev/list-avis){:target="_blank"}.
Cette section se passe en deux grandes parties :
<ul>
<li>tu verras d'abord comment mettre en place la navigation entre les pages de ton application</li>
<li>tu devras ensuite réutiliser tout ce que tu as vu pour le `HomeComponent` pour peupler une nouvelle page : la page *Avis*</li>
</ul>
## Navigation
On veut pouvoir naviguer entre les pages de l'applicatuin, on a donc besoin de plusieurs pages !
>Pour créer une nouvelle page, on doit générer un nouveau composant.
>Vu qu'on veut une page qui affiche les avis, on peux appeler ce composant *review*.
***A toi de jouer en utilisant Angular CLI via ton terminal***
La commande est la même que celle utilisée pour générer le `HomeComponent`; il faudra juste lui donner le nom *review* pour que le composant généré s'appelle `ReviewComponent`.
>Maintenant que nous avons généré `ReviewComponent`, tout est prêt pour faire de la navigation entre nos pages !
On veut rajouter un onglet *Avis* dans notre navbar et que lorsque l'on clique dessus, le `ReviewComponent` s'affiche à la place du `HomeComponent`.
# Le composant avis
Voici un petit [aperçu](https://allocine.takima.dev/list-avis){:target="_blank"} de ce que tu dois essayer de faire. Pas
de panique s'il n'y a pas autant de style et de fonctionnalités !
***L'objectif est que tu réalises ce composant de façon beaucoup moins guidé que pour le `HomeComponent`***
## Objectifs
Tu dois avoir sur la page :
<ul>
<li>un titre</li>
<li>un tableau </li>
</ul>
Dans le tableau, il te faut au minimum 6 colonnes :
<ul>
<li>id de la review</li>
<li>note de la review</li>
<li>texte de la review</li>
<li>date de la review, au format dd/mm/yy</li>
<li>email de l'utilisateur qui a fait l'avis</li>
<li>titre du film qui concerne l'avis</li>
</ul>
## Aide
Le plus dur ici est de créer le tableau, et ce n'est pas de l'Angular !
Grace à Bootstrap c'est super simple ! Regarde la [documentation de Table](https://getbootstrap.com/docs/5.0/content/tables/){:target="_blank"}.
Tu as un petit défi pour la **date**. Le back nous renvoie un format de Date classique et ce n'est pas affichable tel quel.
Tu dois donc formatter la date !! Pour ça, Angular met à disposition un [Pipe](https://angular.dev/guide/pipes){:target="_blank"}.
> ⚠️ Attention, il faut penser à importer `DatePipe` de `@angular/common`.
# Navigation
Actuellement, dans notre `AppComponent` nous affichons la `NavbarComponent` et le `HomeComponent`.
On veut pouvoir afficher le `ReviewComponent` à la place du `HomeComponent` de façon dynamique en fonction de l'url.
> Une url c'est ça: `http://localhost:4200/`.
> Si tu ne vois vraiment pas ce que c'est, tu peux faire un petit tour par sur [cette documentation](https://developer.mozilla.org/fr/docs/Learn/Common_questions/Web_mechanics/What_is_a_URL){:target="_blank"}.
> Généralement, on modifie les urls via des clics sur des liens.
## RouterOutlet
Pour cela Angular dispose d'une directive (qu'il ne faut pas oublier d'importer) : **`<router-outlet>`**. Cette directive permet d'insérer le composant relié à l'url juste en dessous de lui.
Rends-toi dans `app.component.html` et remplace le `<app-home>` par `<router-outlet />`
> Pour info, `<router-outlet></router-outlet>` et `<router-outlet />` sont équivalents
❓ Mais... Comment le `<router-outlet>` connait-il le composant relié à l'url ?
## Les routes
Pour naviguer entre nos pages, on doit définir des routes !
Cela se fait dans le fichier `app.route.ts`.
L'objet `Routes` est une liste qui contient un ou plusieurs objets `Route`.
L'objet `Route` est un objet avec beaucoup de [propriétés optionelles](https://angular.dev/api/router/Route#){:target="_blank"}. Les deux que nous utiliserons sont **path** et **component**.
<ul>
<li> <strong>path</strong> est le bout d'url que l'on veut faire matcher</li>
<li> <strong>component</strong> est le composant lié à ce path (donc celui qu'on affiche quand il y a un match dans l'url)</li>
</ul>
Dans notre cas, on veut 2 routes : une principale pour l'accueil qui affiche le `HomeComponent` et une */review* pour les avis qui affiche le `ReviewComponent`.
```
export const routes: Routes = [
{ path: '', component: HomeComponent},
{ path: 'review', component: ReviewComponent}
];
```
Vérifions que notre constante `routes` est bien utilisée : elle doit se trouver dans le `app.config.ts`.
```
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes)]
};
```
> On voit que l'import de `routes` est bien présent, que le fichier provide le `Router` d'Angular (avec `provideRouter`) et qu'on lui passe bien les routes en paramétres. Parfait ! ⭐
Pour savoir si ce que l'on a fait fonctionne : rajoute */review* dans ton url après ton locahost (`http://localhost:4200/review`). Tu dois voir le contenu HTML de `ReviewComponent` : `<p>review works!</p>`.
***C'est booon, les routes fonctionnent !!***
Maintenant, on veut éviter de devoir entrer en dur des paths dans l'url à la main pour naviguer.
## RouterLink
Dans notre `NavbarComponent`, on peut ajouter un onglet *Avis*.
```
<nav class="navbar navbar-light navbar-expand bg-light ps-5">
<a class="navbar-brand">{{ title | titlecase }}</a>
<a class="nav-item nav-link" href="#">Accueil</a>
<a class="nav-item nav-link" href="#">Avis</a>
</nav>
```
On a donc 2 onglets : **Accueil** et **Avis**. Ce sont des balises `<a>` avec un `href`.
> `href` est un attribut HTML qui permet de définir la destination (en relatif ou en absolue) lorsque l'on clique sur le lien.
En Angular, nous n'utilisons pas `href` mais la directive `routerLink`.
A toi de jouer ! Remplace les `href` par des `routerLink`
❗La valeur du routerLink doit correspondre aux **paths** indiqués dans les `Routes`
> Le chemin du `ReviewComponent` est défini à 'review' dans le fichier `app.route.ts`.
> Par contre, dans la directive routerLink, il faut le spécifier comme "/review" (avec le /).
> routerLink construit l’URL de manière relative au chemin courant. Ajouter un / indique que l’URL doit être construite depuis l’URL de base de l’application (ici http://localhost:4200). Sans la spécification du / dans la directive du routerLink, on irait vers /review/review.
Tu dois donc avoir :
```
<nav class="navbar navbar-light navbar-expand bg-light ps-5">
<a class="navbar-brand">{{ title | titlecase }}</a>
<a class="nav-item nav-link" routerLink="/">Accueil</a>
<a class="nav-item nav-link" routerLink="/review">Avis</a>
</nav>
```
# Communiquer avec l'application
Pour communiquer entre votre Ruban et l'application, nous allons devoir intéragir avec le Broker MQTT.
Le Broker va servir d'intermédiaire pour faire passer nos commandes.
Aujourd'hui, nous avons fourni un client tout prêt et adapté à l'objet connecté pour vous faciliter la vie.
## Configurer le Client
Voici le code qui permet d'instancier le Client qui communique avec le Controleur de LEDs.
Dans l'exemple, les valeurs de configuration sont récupéres depuis le fichier `.env` :
```java
Dotenv dotenv = Dotenv.configure().load();
String clientId = dotenv.get("MQTT_CLIENT_ID");
String mqttHost = dotenv.get("MQTT_HOST");
String mqttUsername = dotenv.get("MQTT_USERNAME");
String mqttPassword = dotenv.get("MQTT_PASSWORD");
// TODO replace by your Device ID
String deviceId = "led-1";
// Instanciation du Client MQTT
this.mqttClient = StandardTakIOTClient.newInstance(mqttHost, clientId, mqttUsername, mqttPassword);
this.ledLightingMiddleware = new LedLightingMiddleware(deviceId);
mqttClient.use(ledLightingMiddleware);
mqttClient.connect();
```
Vous pouvez le voir, il y a deux parties :
* la première où l'on récupère les variables d'environnement (que vous avez placé dans le .env)
* la seconde où on crée le client MQTT (générique) et le **middleware**.
!!! note
Le middleware, c'est un peu notre **Plugin** pour gérer le contrôleur de LEDs.
Notre Middleware s'appelle ledLighting, et c'est grâce à lui qu'on va pouvoir intéragir avec notre module.
!!! warning
Pensez bien à remplacer **deviceId** par le bon deviceId présent sur votre objet. Sinon, cela ne fonctionnera pas.
## Changer l'état d'une LED
Nous l'avons dit dans le briefing : la seule commande d'un contrôleur de LEDs est celle qui permet de dire quelle couleur donner à chaque LED.
Cette commande s'appelle **setLights**.
Comme nous pilotons des **pixels**, nous devrons fournir à chaque fois la liste de tous les pixels et leur valeur **RGB** (Red, Green, Blue).
Dans le programme, il suffit de créer des Pixels, de les mettre dans une liste, et d'appeler le Middleware comme suit :
```java
// On crée une couleur RGB R=223, G=2, B=104
PixelColor futureColor = new PixelColor(223, 2, 104);
// Ici, on crée 25 pixels car on a 25 LEDs
int pixelCount = 25;
List<PixelColor> pixels = new ArrayList<>(pixelCount);
for (int i = 0; i < pixelCount; i++) {
// On met tous nos pixels de la même couleur
pixels.add(futureColor);
}
// On prépare le message à envoyer au Broker MQTT
var message = new SetLightsMessage(pixels);
// On utilise le middleware pour l'envoyer
ledLightingMiddleware.publishSetLights(message);
// C'est fini !
```
## Méthodes utilitaires
Pour vous faciliter la vie, nous avons mis à votre disposition plusieurs méthodes utilitaires :
**ofRepeated :**
Permet de créer une Liste de pixels tous de la même couleur
Ce code :
```java
List<PixelColor> pixels = ListUtils.ofRepeated(myColor, pixelCount);
```
Est équivalent à celui-ci :
```java
List<PixelColor> pixels = new ArrayList<>(pixelCount);
for (int i = 0; i < pixelCount; i++) {
// On met tous nos pixels de la même couleur
pixels.add(myColor);
}
```
**Colors.XXX.value() :**
Donne une quinzaine couleurs standard pour aller plus vite
```java
PixelColor black = Colors.BLACK.value();
```
**TimerUtils.sleepMillis(long millis) :**
Permet de temporiser l'exécution de votre application pendant X millisecondes.
```java
// Pause pendant 10 secondes
TimerUtils.sleepMillis(10_000);
```
# Les Rubans de LEDs
## WS2812B
Tous les modèles de LEDs contiennent un type de LED appelées **WS2812B**.
Le principe de ces LEDs est qu'elles sont :
* RGB (Red, Green, Blue, donc toutes les couleurs)
* Indexées (chaque LED peut être pilotée indépendamment)
Néanmoins, nous avons plusieurs modèles à votre disposition pour ce Hackathon, parmi lequel vous allez devoir faire un choix.
## Le LED-Strip
![](../assets/ws2812b-led-strip.png){: style="height:250px"}
Le LED-Strip, c'est le Ruban à LED, et il a deux avantages :
* Il n'a qu'une dimension (ligne)
* Il est assez long et peut donc très bien faire un bel instrument de déco ou d'ambiance
Utilisez le pour toutes les applications luminaires, ambiance etc...
## La Matrice de LEDs
![](../assets/ws2812b-led-matrix.jpg){: style="height:250px"}
Les matrices de LEDs, c'est comme un écran avec des pixels.
Nous en avons plusieurs modèles :
* 8x8 (64 pixels)
* 32x8 (256 pixels)
* 16x16 (256 pixels)
Les Matrices sont super adaptées pour le texte ou pour dessiner des figures ou des animations simples (émojis, panneaux, signalisations etc...)
Utilisez le pour toutes ces applications.
!!! note
Les matrices de pixels sont en deux dimensions, mais sont quand même adressées de manière unidimensionnelle. Il va donc falloir adapter les indexes de votre programme pour que la matrice puisse dessiner correctement.
Vous ne pourrez pas dessiner en "row, col"
!!! warning
Les matrices ont une haute densité de Pixels et donc tirent beaucoup de courant. Vous ne pouvez et ne devez pas utiliser 100% des Pixels en blanc, car vous pourriez faire griller les LEDs ou l'alimentation.
Préférez donc des couleurs sombres pour habiller le fond, et des couleurs claires pour les pixels importants
## Le Cercle de LEDs
![](../assets/ws2812b-led-ring.jpeg){: style="height:250px"}
Notre dernière manière de faire de la LED, c'est d'utiliser les LED Rings (ou cercles de LEDs).
Les Rings sont adaptés à tout ce qui va pouvoir représenter une jauge, ou des éléments circulaires (horloge, compas).
Ils sont la manière la plus simple de les représenter.
# La Soutenance
![](assets/unicorn_logo.png){: style="height:250px;width:250px"}
**Tu as trouvé ton concept et ça y est, tu as commencé à t'y mettre !**
Comme nous avons l'habitude de voir de jeunes Licornes à Unicorn Corporation, nous voulions te donner quelques guidelines pour ta soutenance de fin de journée.
!!!warning
Le Hackathon s'arrête à 17h. Vous ne pourrez plus coder car ce sera le début des soutenances
## Qui sera le Jury ?
Le Jury sera composé de l'équipe qui t'encadre aujourd'hui, plus quelques autres personnes conviées pour l'occasion.
Leurs consignes ? Évaluer l'équipe qui a le projet le plus réussi, au travers de différents axes :
* Qualité de la soutenance / qualité du pitch
* Qualité et niveau de préparation des slides
* Coolitude du concept
* Niveau d'avancement du projet / des dashboards / de la démo
## Les Tips des anciennes Licornes
Nous avons demandé aux anciennes licornes ce qu'elles avaient comme conseils pour les futures promotions.
Voici ce qu'elles ont dit :
* Le hackathon c'est un jeu de vitesse avant tout. Il vaut mieux ne pas être trop ambitieux au départ.
* Une partie de l'équipe devrait travailler sur les slides dès 15h !
* Il faut s'arrêter bien avant 17h (16h30 conseillé) pour avoir le temps de répéter la soutenance
* La démo doit être parfaitement répétée pour faire son effet !
* L'humour et la légèreté passent très bien !
* Utilisez des templates tout prêts sur Google Slides pour aller plus vite (ou autre logiciel que vous préférez)
* Sollicitez et utilisez un maximum vos Coaches pour vous aider à avancer plus vite !
**C'est parti !**
......@@ -16,10 +16,10 @@ nav:
- Le app-component: 'premiere-page/app-component.md'
- Ton premier composant: 'premiere-page/navbar.md'
- Le @Input: 'premiere-page/input.md'
- Ruban de LEDs:
- Les Rubans: 'ruban-led/index.md'
- Communiquer avec l'application: 'ruban-led/create_project.md'
- Soutenance : 'soutenance.md'
- Page d'avis:
- Création du composant: 'avis-page/create-component.md'
- La navigation: 'avis-page/navigation.md'
- Le composant Avis: 'avis-page/implem-component.md'
theme:
name: material
language: fr
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment