Merge remote-tracking branch 'refs/remotes/origin/main'
This commit is contained in:
99
README.md
99
README.md
@@ -1,48 +1,89 @@
|
|||||||
# hackathon
|
# FrisbyEE (Projet Hackathon)
|
||||||
|
|
||||||
## Pour lancer
|
Ce projet contient : un backend Spring Boot et un frontend React en TypeScript développé lors du hackathon. L'authentification est gérée par Keycloak et la base de données est PostgreSQL; les deux peuvent être lancés via Docker.
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Présentation rapide
|
||||||
|
- **Backend** : Spring Boot (Java 17) dans `back_end/`
|
||||||
|
- **Frontend** : React et TypeScript dans `front_end/`
|
||||||
|
- **Auth** : Keycloak (voir `keycloak/` pour la thème et configuré via `docker-compose.yml`)
|
||||||
|
- **Base de données** : PostgreSQL (configuré via `docker-compose.yml`)
|
||||||
|
|
||||||
|
## Pré-requis
|
||||||
|
- Java 17
|
||||||
|
- Maven (utiliez `mvn`)
|
||||||
|
- Node.js et npm
|
||||||
|
- Docker et Docker Compose
|
||||||
|
|
||||||
|
## Installation et démarrage
|
||||||
|
1. Récupérez le dépôt et placez-vous à la racine du projet.
|
||||||
|
2. Démarrez Keycloak et PostgreSQL avec Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
sudo docker compose up -d
|
sudo docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
### back_end
|
3. Backend: construire et lancer (depuis la racine du projet):
|
||||||
cd back_end
|
|
||||||
|
|
||||||
#### Pour installer java 17
|
```bash
|
||||||
sudo apt install openjdk-17-jdk
|
cd back_end
|
||||||
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
|
./mvn clean install
|
||||||
export PATH=$JAVA_HOME/bin:$PATH
|
./mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
#### Clean
|
4. Frontend: installer les dépendances et démarrer :
|
||||||
mvn clean install
|
|
||||||
|
|
||||||
#### Pour lancer back_end
|
```bash
|
||||||
mvn spring-boot:run
|
|
||||||
|
|
||||||
### front_end
|
|
||||||
cd front_end
|
cd front_end
|
||||||
|
npm install
|
||||||
#### Install
|
|
||||||
npm install
|
|
||||||
|
|
||||||
#### Lancer front_end
|
|
||||||
npm start
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
#### Docker
|
Le serveur de développement du frontend écoute par défaut sur `http://localhost:3000`, le backend sur `http://localhost:8080`, et api sur `http://localhost:8081` sauf configuration différente.
|
||||||
|
|
||||||
|
## Commandes utiles
|
||||||
|
- Arrêter et supprimer tous les conteneurs Docker:
|
||||||
|
|
||||||
|
```bash
|
||||||
sudo docker stop $(sudo docker ps -a -q)
|
sudo docker stop $(sudo docker ps -a -q)
|
||||||
|
sudo docker rm $(sudo docker ps -a -q)
|
||||||
|
```
|
||||||
|
|
||||||
#### Pour acceder sur docker
|
- Ouvrir un shell Postgres dans le conteneur en cours d'exécution (exemple : conteneur `frisbyee-postgres`):
|
||||||
|
|
||||||
|
```bash
|
||||||
sudo docker exec -it frisbyee-postgres psql -U frisbyee_user -d frisbyee
|
sudo docker exec -it frisbyee-postgres psql -U frisbyee_user -d frisbyee
|
||||||
|
# puis, par exemple : \dt ou SELECT * FROM session;
|
||||||
|
```
|
||||||
|
|
||||||
#### Voir les données:
|
## Keycloak / Thème de connexion
|
||||||
\dt
|
- Au début, il faut crée run realm qui s'appelle `Frisbyee_realm`, ensuite dans ce realm, créez un `Frisbyee_client` avec ce config debug:
|
||||||
SELECT * FROM session;
|
```
|
||||||
|
ROOT URL: http://localhost:3000/
|
||||||
|
HOME URL: http://localhost:3000/
|
||||||
|
Valid redirect URIs: http://localhost:3000/*
|
||||||
|
Web origins: *
|
||||||
|
```
|
||||||
|
- Après, ajoutez les rôles : `admin`, `coach`, `athlete`
|
||||||
|
- Et, mettez chaque groupe `ADMIN`, `COACH`, `ATHLETE` et mapping chaque rôle pour chaque groupe.
|
||||||
|
- Dans User Registration, mettez le `defaut groupe`: `ATHLETE` et activez le user self registration.
|
||||||
|
|
||||||
|
Pour appliquer le thème de connexion personnalisé fourni dans `keycloak/themes/frisbyee` :
|
||||||
|
- Ouvrez la console d'administration Keycloak -> sélectionnez le realm -> `Realm Settings` -> modifiez le `Display name` si vous le souhaitez.
|
||||||
|
- Dans `Themes`, définissez `Login Theme` sur `frisbyee` puis enregistrez.
|
||||||
|
|
||||||
|
|
||||||
#### Appliquer le CSS pour la page de login Keycloak
|
## Configuration / Environnement
|
||||||
|
- Les propriétés du backend se trouvent dans `back_end/src/main/resources/application.properties`.
|
||||||
Sur la console Keycloak aller dans realm setting
|
- Le frontend utilise `public/keycloak.json` pour la configuration du client Keycloak.
|
||||||
-> Changer le display name (par exemple: Bienvenue sur Frisbyee !)
|
- Assurez-vous que le client Keycloak et le realm correspondent aux valeurs utilisées par les deux applications.
|
||||||
-> Theme puis changer le login theme sur frisbyee
|
|
||||||
|
|
||||||
|
## Contribution
|
||||||
|
- Thibaut ROCHAS
|
||||||
|
- Tuan Minh VU
|
||||||
|
- Amäel KESTEMAN
|
||||||
|
- Alexis LEBOEUF
|
||||||
## Domain model class diagram
|
## Domain model class diagram
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
|
|||||||
@@ -242,9 +242,9 @@ textarea::placeholder {
|
|||||||
|
|
||||||
/* Select */
|
/* Select */
|
||||||
select {
|
select {
|
||||||
|
background-color: var(--tint2);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
background-color: var(--tint3);
|
border: 1px solid var(--tint4);
|
||||||
border: 2px solid var(--tint5);
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -260,6 +260,7 @@ select:focus {
|
|||||||
select option {
|
select option {
|
||||||
background-color: var(--tint2);
|
background-color: var(--tint2);
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
@@ -364,7 +365,7 @@ button.add:hover,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Modal */
|
/* Modal */
|
||||||
.modal {
|
.modalContent {
|
||||||
background-color: var(--tint2);
|
background-color: var(--tint2);
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
@@ -373,8 +374,22 @@ button.add:hover,
|
|||||||
border: 2px solid var(--green-primary);
|
border: 2px solid var(--green-primary);
|
||||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
|
||||||
position: relative;
|
position: relative;
|
||||||
|
max-height:100%;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background: rgba(0,0,0,0.25);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
max-height:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.modal-overlay {
|
.modal-overlay {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ export class Session{
|
|||||||
isRecurrent: this.isRecurrent,
|
isRecurrent: this.isRecurrent,
|
||||||
creneau: this.creneau.toISOString(),
|
creneau: this.creneau.toISOString(),
|
||||||
duree: this.duree,
|
duree: this.duree,
|
||||||
groupe: "", //TODO
|
groupe: this.groupe,
|
||||||
coachId: this.coach?.id ?? null,
|
coachId: this.coach?.id ?? null,
|
||||||
athleteIds: [],
|
athleteIds: [],
|
||||||
activiteIds: []
|
activiteIds: []
|
||||||
|
|||||||
@@ -13,22 +13,10 @@ export function Modal({ isOpen, onClose, children }: ModalProps) {
|
|||||||
if (!isOpen) return null
|
if (!isOpen) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="modal" onClick={onClose}>
|
||||||
style={{
|
<div className="modalContent" onClick={(e) => e.stopPropagation()}>
|
||||||
position: "fixed",
|
{children}
|
||||||
inset: 0,
|
</div>
|
||||||
backgroundColor: "rgba(0,0,0,0.25)",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
zIndex: 1000,
|
|
||||||
}}
|
|
||||||
onClick={onClose}
|
|
||||||
>
|
|
||||||
<div className="modal" onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,20 @@ export const CreateSession = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Groupe:</th>
|
<th>Groupe:</th>
|
||||||
|
<th>
|
||||||
|
<select
|
||||||
|
onChange={(e) => {
|
||||||
|
const v = (e.target as HTMLSelectElement).value;
|
||||||
|
setGroupe(v as Groupe)
|
||||||
|
console.log(v);
|
||||||
|
}}>
|
||||||
|
<option value=""> Sans groupe</option>
|
||||||
|
<option value="Loisir">Loisir</option>
|
||||||
|
<option value="Entrainement">Entrainement</option>
|
||||||
|
<option value="Competition">Competition</option>
|
||||||
|
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Creneau:</th>
|
<th>Creneau:</th>
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ export async function createSessionAPI(session: Session): Promise<Session> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log("GROUPE = " + session.groupe);
|
||||||
const response = await api.post<SessionDTO>("/session/create", session.toDTO());
|
const response = await api.post<SessionDTO>("/session/create", session.toDTO());
|
||||||
const sessionRes:Session = new Session(response.data);
|
const sessionRes:Session = new Session(response.data);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
|
|||||||
Reference in New Issue
Block a user