From 533dfc0327bd3ff9a27b454a84c9a20c8f3928d1 Mon Sep 17 00:00:00 2001 From: Godlewski Stanislas <stanislas.godlewski@student-cs.fr> Date: Thu, 21 Nov 2024 18:13:31 +0100 Subject: [PATCH 01/12] Version fonctionnelle objets --- .DS_Store | Bin 8196 -> 8196 bytes .../0002_alter_borrowrequest_id_object.py | 20 ++++ Borrowing/models.py | 4 +- .../templates/Borrowing/borrow_request.html | 2 +- .../templates/Borrowing/borrowed_items.html | 4 +- Borrowing/templates/Borrowing/borrowing.html | 4 +- Borrowing/views.py | 12 +-- Communities/models.py | 6 +- .../Communities/list_objects_admin.html | 2 +- .../Communities/list_objects_community.html | 4 +- object/forms.py | 8 +- ...objectcategory_object_category_and_more.py | 55 +++++++++++ object/models.py | 22 +++-- object/scripts/data.csv | 79 +++++++++++++++ object/scripts/script.py | 59 +++++++++++ object/templates/object/modify_object.html | 17 ++-- object/templates/object/object_list.html | 23 ++--- .../templates/object/select_user_objects.html | 16 +++ object/urls.py | 5 +- object/views.py | 93 +++++++++--------- 20 files changed, 335 insertions(+), 100 deletions(-) create mode 100644 Borrowing/migrations/0002_alter_borrowrequest_id_object.py create mode 100644 object/migrations/0005_rename_objectcategory_object_category_and_more.py create mode 100644 object/scripts/data.csv create mode 100644 object/scripts/script.py create mode 100644 object/templates/object/select_user_objects.html diff --git a/.DS_Store b/.DS_Store index d2d8f002b55ec80f5d911c47e0cae1b0dbdb9bf9..a7e587f147e929c1c5b8df694ce81e223e531a40 100644 GIT binary patch delta 42 ycmZp1XmOa}&&a<qU^hP_|7IS6|BRCpg{N({6lr7Jtj_a*c{97jH<pbR?92c%`wk8O delta 195 zcmZp1XmOa}&nU7nU^hRb$Yvga|BRws3@Hpr40;U34229i44Dii45<vplO+V?`PmsV zfV^CwXfi`SL)l~>EMgl3j!UDdD+?~l%gN76XJBApoXjCK(_E0DfT0LzYB3P!0ZmK< z;!L24c|cnWfUtz2!ZRm7IVmSU38+T^sI41F>usJUG?8&*g9p=Qc8PB+lT(EcZESF5 F0sxnSFR}mt diff --git a/Borrowing/migrations/0002_alter_borrowrequest_id_object.py b/Borrowing/migrations/0002_alter_borrowrequest_id_object.py new file mode 100644 index 0000000..a750bf2 --- /dev/null +++ b/Borrowing/migrations/0002_alter_borrowrequest_id_object.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.3 on 2024-11-21 16:27 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Borrowing', '0001_initial'), + ('object', '0005_rename_objectcategory_object_category_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='borrowrequest', + name='id_object', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='object.userobject'), + ), + ] diff --git a/Borrowing/models.py b/Borrowing/models.py index 00eaa63..78af578 100644 --- a/Borrowing/models.py +++ b/Borrowing/models.py @@ -1,10 +1,10 @@ from django.db import models from django.contrib.auth.models import User -from object.models import Object +from object.models import UserObject # Create your models here. class BorrowRequest(models.Model): id_borrower = models.ForeignKey(User, on_delete=models.CASCADE) - id_object = models.ForeignKey(Object, on_delete=models.CASCADE) + id_object = models.ForeignKey(UserObject, on_delete=models.CASCADE) is_accepted = models.BooleanField(default=False) is_finished = models.BooleanField(default=False) diff --git a/Borrowing/templates/Borrowing/borrow_request.html b/Borrowing/templates/Borrowing/borrow_request.html index ce61028..e0443b0 100644 --- a/Borrowing/templates/Borrowing/borrow_request.html +++ b/Borrowing/templates/Borrowing/borrow_request.html @@ -8,7 +8,7 @@ <ul> {% for request in requests %} {% if id_user == request.id_object.id_lender.id and not request.is_finished %} - <li>{{request.id_object.name}} - Demandé par {{request.id_borrower.username}}</li> + <li>{{request.id_object.object.name}} - Demandé par {{request.id_borrower.username}}</li> {% if request.id_object.is_borrowed%} {% if request.is_accepted %} <button class="btn btn-success" type = "submit" disabled>Acceptée !</button> diff --git a/Borrowing/templates/Borrowing/borrowed_items.html b/Borrowing/templates/Borrowing/borrowed_items.html index ff54c50..9540884 100644 --- a/Borrowing/templates/Borrowing/borrowed_items.html +++ b/Borrowing/templates/Borrowing/borrowed_items.html @@ -7,7 +7,7 @@ <ul> {% for request in requests %} {% if request.id_borrower == user and not request.is_finished%} - <li>{{request.id_object.name}} - Demandé à {{request.id_object.id_lender.username}}: + <li>{{request.id_object.object.name}} - Demandé à {{request.id_object.id_lender.username}}: {% if request.is_accepted %} <p>Demande acceptée : Prenez contact avec {{request.id_object.id_lender.first_name}} à {{request.id_object.id_lender.email}} </p> <form method = "POST"> @@ -16,7 +16,7 @@ </form> {% elif request.id_object.is_borrowed %} <p> L'objet est déjà emprunté :(</p> - <form method = "POST"> + <form method = "POST">x {% csrf_token %} <button class="btn btn-danger" type = "submit" value = {{request.id}} id = "cancelOrEnd" name = "cancelOrEnd">Annuler la demande</button> </form> diff --git a/Borrowing/templates/Borrowing/borrowing.html b/Borrowing/templates/Borrowing/borrowing.html index faef3d6..fdb7e16 100644 --- a/Borrowing/templates/Borrowing/borrowing.html +++ b/Borrowing/templates/Borrowing/borrowing.html @@ -9,10 +9,10 @@ {% if object in filtered_objects%} <form method = "POST"> {% csrf_token %} - <li>{{object.name}}: <button class="btn btn-success" value = {{object.id}} name = "item" id = "item"> Demander </button></li> + <li>{{object.object.name}} à {{object.id_lender.first_name}} {{object.id_lender.last_name}}: <button class="btn btn-success" value = {{object.id}} name = "item" id = "item"> Demander </button></li> </form> {% else %} - <li>{{object.name}}: <button class="btn btn-danger" value = {{object.id}} name = "item" id = "item" disabled> Déjà demandé ! </button></li> + <li>{{object.object.name}} à {{object.id_lender.first_name}} {{object.id_lender.last_name}}: <button class="btn btn-danger" value = {{object.id}} name = "item" id = "item" disabled> Déjà demandé ! </button></li> {% endif %} {% endfor %} </ul> diff --git a/Borrowing/views.py b/Borrowing/views.py index 379d0d2..20e295f 100644 --- a/Borrowing/views.py +++ b/Borrowing/views.py @@ -1,6 +1,6 @@ from django.shortcuts import render from django.http import HttpResponse -from object.models import Object, ObjectCategory +from object.models import Object, ObjectCategory, UserObject from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from . import models @@ -14,17 +14,17 @@ def borrowing(request): #Vue permettant à l'utilisateur de faire une demande communities = CommunityMembership.objects.filter(user = request.user).values("community") lender = CommunityMembership.objects.filter(community__in=communities).values("user") - listObjects = Object.objects.filter(id_lender__in=lender) + listObjects = UserObject.objects.filter(id_lender__in=lender) if request.method == "POST": #Cas où il effectue une nouvelle demande form = forms.borrowing(request.POST) if form.is_valid(): #Création de la demande dans la base de données - item = Object.objects.get(id = form.cleaned_data["item"]) - borrowRequest = models.BorrowRequest.objects.create(id_object = item, id_borrower = request.user) + item = UserObject.objects.get(id = form.cleaned_data["item"]) + borrowRequest = BorrowRequest.objects.create(id_borrower = request.user, id_object = item) #Création d'un contexte permettant d'éviter de faire plusieurs fois la même demande - doublons = models.BorrowRequest.objects.values("id_object", "id_borrower", "is_finished") + doublons = BorrowRequest.objects.values("id_object", "id_borrower", "is_finished") contexte = { "objects": listObjects, "user" : request.user, @@ -49,7 +49,7 @@ def borrowing(request): @login_required def borrowing_test(request, object_id): - object = Object.objects.get(id=object_id) + object = UserObject.objects.get(id=object_id) borrowRequest = models.Borrow.objects.create(id_object = object, id_borrower = request.user) return render(request, "Borrowing/thanks.html") diff --git a/Communities/models.py b/Communities/models.py index 0da6124..853faf0 100644 --- a/Communities/models.py +++ b/Communities/models.py @@ -1,6 +1,6 @@ from django.db import models from django.contrib.auth.models import User -from object.models import Object +from object.models import UserObject class Community(models.Model): name = models.CharField(max_length=100) @@ -23,13 +23,13 @@ class Community(models.Model): Retourne tous les objets prêtés par des membres de cette communauté. ''' # Utiliser une requête différée pour récupérer les membres de la communauté - from .models import CommunityMembership, Object + from .models import CommunityMembership, UserObject # Obtenir les utilisateurs membres de la communauté member_ids = CommunityMembership.objects.filter(community=self).values_list('user_id', flat=True) # Filtrer les objets prêtés par ces membres - return Object.objects.filter(id_lender__id__in=member_ids) + return UserObject.objects.filter(id_lender__id__in=member_ids) class CommunityMembership(models.Model): diff --git a/Communities/templates/Communities/list_objects_admin.html b/Communities/templates/Communities/list_objects_admin.html index fd06619..4fcfdf3 100644 --- a/Communities/templates/Communities/list_objects_admin.html +++ b/Communities/templates/Communities/list_objects_admin.html @@ -5,7 +5,7 @@ <ul> {% for obj in objects %} <li> - {{ obj.name }} + {{ obj.object.name }} <form method="POST" action="{% url 'delete_object' community.id obj.id %}"> {% csrf_token %} <button type="submit" class="btn btn-danger">Supprimer</button> diff --git a/Communities/templates/Communities/list_objects_community.html b/Communities/templates/Communities/list_objects_community.html index 1234444..357726f 100644 --- a/Communities/templates/Communities/list_objects_community.html +++ b/Communities/templates/Communities/list_objects_community.html @@ -25,9 +25,9 @@ <tbody> {% for obj in objects %} <tr> - <td>{{ obj.name }}</td> + <td>{{ obj.object.name }}</td> <td>{{ obj.description }}</td> - <td>{{ obj.objectCategory.name }}</td> + <td>{{ obj.object.category.name }}</td> <td>{{ obj.id_lender.username }}</td> </tr> diff --git a/object/forms.py b/object/forms.py index 1caf178..1ec4838 100644 --- a/object/forms.py +++ b/object/forms.py @@ -4,5 +4,11 @@ from .models import Object class ObjectForm(forms.ModelForm): class Meta: model = Object - fields = ['objectCategory', 'description', 'name'] + fields = ['name', 'category'] +class UserObjectSelectForm(forms.Form): + objects = forms.ModelMultipleChoiceField( + queryset=Object.objects.all(), + widget=forms.CheckboxSelectMultiple, + required=False + ) diff --git a/object/migrations/0005_rename_objectcategory_object_category_and_more.py b/object/migrations/0005_rename_objectcategory_object_category_and_more.py new file mode 100644 index 0000000..5c408ae --- /dev/null +++ b/object/migrations/0005_rename_objectcategory_object_category_and_more.py @@ -0,0 +1,55 @@ +# Generated by Django 5.1.3 on 2024-11-21 16:00 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('object', '0004_object_is_borrowed'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.RenameField( + model_name='object', + old_name='objectCategory', + new_name='category', + ), + migrations.RemoveField( + model_name='object', + name='description', + ), + migrations.RemoveField( + model_name='object', + name='id_lender', + ), + migrations.RemoveField( + model_name='object', + name='is_borrowed', + ), + migrations.RemoveField( + model_name='objectcategory', + name='description', + ), + migrations.CreateModel( + name='Selection', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='object.object')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='UserObject', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.CharField(max_length=1000, null=True)), + ('is_borrowed', models.BooleanField(default=False)), + ('id_lender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('object', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='object.object')), + ], + ), + ] diff --git a/object/models.py b/object/models.py index 19af356..94db28e 100644 --- a/object/models.py +++ b/object/models.py @@ -6,19 +6,29 @@ from django.contrib.auth.models import User class ObjectCategory(models.Model): ''' Les différentes Catégories d'objet possible''' name = models.CharField(max_length=100) - description = models.TextField(max_length=1000) def __str__(self): return self.name - class Object(models.Model): + name = models.CharField(max_length = 100) + category = models.ForeignKey(ObjectCategory, on_delete=models.CASCADE) + + def __str__(self): + return self.name + + + +class UserObject(models.Model): ''' Chaque objet vient d'une catégorie possible qui a été approuvé''' - name = models.CharField(max_length=100) - description = models.CharField(max_length=1000) - objectCategory = models.ForeignKey(ObjectCategory, on_delete=models.CASCADE) + description = models.CharField(max_length=1000, null=True) + object = models.ForeignKey(Object, on_delete=models.CASCADE) id_lender = models.ForeignKey(User, on_delete=models.CASCADE) is_borrowed = models.BooleanField(default=False) # Attribut qui sera modifié dans Borrowing def __str__(self): - return self.description \ No newline at end of file + return f"Objet {self.object.name} par {self.id_lender.first_name} : {self.description}" + +class Selection(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + object = models.ForeignKey(Object, on_delete=models.CASCADE) diff --git a/object/scripts/data.csv b/object/scripts/data.csv new file mode 100644 index 0000000..7c1aae2 --- /dev/null +++ b/object/scripts/data.csv @@ -0,0 +1,79 @@ +Catégorie,Objet +Bien-être,Appareil chauffe pierre +Bien-être,Table de massage +Bricolage,Perceuse - visseuse +Bricolage,Visseuse sans fil +Bricolage,Perforatrice +Bricolage,Scie sauteuse +Bricolage,Scie circulaire +Bricolage,Boite à onglet +Bricolage,Scie à métaux +Bricolage,Rainureuse +Bricolage,Scie à onglet électrique +Bricolage,Kit pose parquet +Bricolage,Ponceuse électrique +Bricolage,Sacs à gravat +Bricolage,Seaux pour évacuer des gravats ou terre +Bricolage,Echelle de couvreur +Bricolage,Escabeau +Bricolage,Décapeur thermique +Bricolage,Fer à souder +Bricolage,Scie sabre +Bricolage,Harnais de sécurité +Bricolage,Meuleuse +Bricolage,Longue mèche pour percer le béton +Cuisine,Appareil à raclette +Cuisine,Appareil à fondue +Cuisine,Couteau à huîtres +Cuisine,Pierrade +Cuisine,Bouilloire +Cuisine,Cafetière +Déménagement,Cartons +Déménagement,Film de protection +Maison,Paperboard +Maison,Projecteur +Maison,Déshumidificateur +Maison,Aspirateur à eau +Jardinage,Taille-haie +Jardinage,Tondeuse à gazon +Jardinage,Echelle +Jardinage,Brouette +Jardinage,Motobineuse électrique +Jardinage,Fourche +Jardinage,Rateau +Jardinage,Sécateur emmanché +Jardinage,Grand sécateur emmanché +Bricolage,Pistolet à colle +Maison,Machine à coudre +Jardinage,Tuyau d arrosage +Mobilité,Vélo homme +Mobilité,Vélo femme +Mobilité,Vélo enfant +Petite enfance,Réhausseur enfants pour voiture +Petite enfance,Lit pliant +Petite enfance,Chaise haute +Petite enfance,Poussette +Petite enfance,Maxi-cosi +Réception,Verrines +Réception,Tonnelle +Réception,Verres +Réception,Flûtes à champagne +Réception,Chaises +Réception,Boite isotherme +Réception,Blocs réfrigérants +Réception,Table +Voyage,Valise cabine +Voyage,Grande valise +Voyage,Sac à dos de randonnée +Voyage,Tente +Voyage,Sac de couchage +Voyage,Porte Vélo +Bricolage,Aspirateur à travaux +Maison,Verres à orangeade +Maison,Mutlicrêpes +Maison,Crépière +Services,Support informatique +Services,Plomberie +Services,Petites réparation +Services,Baby-sitting +Services,Soutien scolaire \ No newline at end of file diff --git a/object/scripts/script.py b/object/scripts/script.py new file mode 100644 index 0000000..d61a599 --- /dev/null +++ b/object/scripts/script.py @@ -0,0 +1,59 @@ +import os +import sys +import django +import csv + +# Configuration de l'environnement Django +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) # Répertoire du script +PROJECT_ROOT = os.path.abspath(os.path.join(SCRIPT_DIR, "../../..")) # Répertoire racine du projet +sys.path.append(PROJECT_ROOT) + +# Définir les paramètres Django +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "communityshare.settings") +django.setup() + +# Importer les modèles de votre application Django +from object.models import ObjectCategory, Object + +def create_objects_from_csv(file_name="data.csv"): + """ + Lit un fichier CSV et crée des instances de ObjectCategory et Object + en évitant les doublons pour les catégories et les objets. + """ + file_path = os.path.join(SCRIPT_DIR, file_name) # Construire le chemin complet du fichier CSV + + # Vérifier si le fichier existe + if not os.path.exists(file_path): + print(f"Erreur : Le fichier {file_name} est introuvable.") + return + + # Lire le fichier CSV et importer les données + with open(file_path, mode="r", encoding="utf-8") as csvfile: + reader = csv.reader(csvfile) + + # Ignorer la première ligne si elle contient des en-têtes + next(reader, None) + + for row in reader: + if len(row) < 2: + continue # Si la ligne est vide ou mal formatée, on l'ignore + + category_name, object_name = row[0].strip(), row[1].strip() + + # Créer ou récupérer la catégorie + category, created_category = ObjectCategory.objects.get_or_create(name=category_name) + if created_category: + print(f"Catégorie créée : {category.name}") + else: + print(f"Catégorie existante : {category.name}") + + # Créer ou récupérer l'objet associé à cette catégorie + obj, created_object = Object.objects.get_or_create(name=object_name, category=category) + if created_object: + print(f"Objet créé : {obj.name} dans la catégorie {category.name}") + else: + print(f"Objet existant : {obj.name} dans la catégorie {category.name}") + +# Exécuter la fonction +if __name__ == "__main__": + create_objects_from_csv("data.csv") \ No newline at end of file diff --git a/object/templates/object/modify_object.html b/object/templates/object/modify_object.html index 3baab6d..e3fdbfb 100644 --- a/object/templates/object/modify_object.html +++ b/object/templates/object/modify_object.html @@ -1,13 +1,14 @@ {% extends 'base.html' %} -{% block title %}Modifier un Objet{% endblock %} - {% block content %} -<h2>Modifier l'Objet</h2> -<form method="post"> + <h1>Modifier la description de l'objet : {{ user_object.object.name }}</h1> + + <form method="POST"> {% csrf_token %} - {{ form.as_p }} - <button type="submit">Modifier</button> -</form> -<a href="{% url 'object_list' %}">Retour à la liste</a> + <textarea name="description" rows="4" cols="50" placeholder="Entrez une description pour cet objet">{{ user_object.description }}</textarea> + <button type="submit">Enregistrer</button> + </form> + + <p><a href="{% url 'object_list' %}">Retour aux objets</a></p> {% endblock %} + diff --git a/object/templates/object/object_list.html b/object/templates/object/object_list.html index 7b510f9..6449548 100644 --- a/object/templates/object/object_list.html +++ b/object/templates/object/object_list.html @@ -6,40 +6,34 @@ <h2>Liste de mes objets ! </h2> <!-- Bouton Ajouter un objet --> -<div class="container-fluid"> -<a href="{% url 'add_object' %}" class="btn btn-success mb-3"> - Ajouter un objet +<a href="{% url 'select_user_objects' %}" class="btn btn-success mb-3"> + Ajouter des objets </a> <!-- Bouton Gérer mes sollicitations --> <a href="{% url 'borrow_request' %}" class="btn btn-success mb-3"> Gérer mes sollicitations </a> -</div> -<table border="1" class="table"> +<table border="1"> <thead> <tr> <th>Name</th> - <th>Description</th> <th>Catégorie</th> - <th>Actions</th> + <th>Description</th> </tr> </thead> <tbody> {% for obj in objects %} <tr> - <td> {% if obj.name %} - {{ obj.name }} - {% endif %} + <td> + {{ obj.object.name }} </td> <td> - <a href="{% url 'object_detail' obj.id %}">{{ obj.description }}</a> + {{obj.object.category.name}} </td> - <td>{{ obj.objectCategory.name }}</td> <td> - <a href="{% url 'modify_object' obj.id %}">Modifier</a> | - <a href="{% url 'delete_object' obj.id %}">Supprimer</a> + <a href="{% url 'modify_object' obj.id %}">Ajouter une description</a> | </td> @@ -50,5 +44,4 @@ </tbody> </table> - {% endblock %} diff --git a/object/templates/object/select_user_objects.html b/object/templates/object/select_user_objects.html new file mode 100644 index 0000000..4e4df06 --- /dev/null +++ b/object/templates/object/select_user_objects.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} + +{% load crispy_forms_tags %} + +{% block content %} + + <h1>Ajouter des objets que vous pouvez prêter</h1> + <form method="POST"> + {% csrf_token %} + {{ form|crispy}} + <button type="submit">Enregistrer la sélection</button> + </form> + +{% endblock content %} + + diff --git a/object/urls.py b/object/urls.py index 0b12c46..379dce8 100644 --- a/object/urls.py +++ b/object/urls.py @@ -3,8 +3,7 @@ from . import views urlpatterns = [ path('', views.object_list, name='object_list'), # Afficher tous les objets - path('add/', views.add_object, name='add_object'), # Ajouter un objet - path('<int:object_id>/', views.object_detail, name='object_detail'), # Détail d'un objet + path('add/', views.select_user_objects, name='select_user_objects'), # Ajouter un objet path('<int:object_id>/modify/', views.modify_object, name='modify_object'), # Modifier un objet - path('<int:object_id>/delete/', views.delete_object, name='delete_object'), # Supprimer un objet ] + diff --git a/object/views.py b/object/views.py index 6918672..85c0c12 100644 --- a/object/views.py +++ b/object/views.py @@ -1,7 +1,6 @@ - from django.shortcuts import render, redirect, get_object_or_404 -from .forms import ObjectForm -from .models import Object +from .forms import ObjectForm, UserObjectSelectForm +from .models import Object, UserObject, ObjectCategory, Selection from django.contrib.auth.decorators import login_required ''' @@ -23,58 +22,56 @@ Structure la page en : @login_required def object_list(request): '''Interface qui propose tous les objets que l'utilisateur peut prêter''' - objects = Object.objects.filter(id_lender=request.user) + objects = UserObject.objects.filter(id_lender=request.user) return render(request, 'object/object_list.html', {'objects': objects}) -@login_required -def object_detail(request, object_id): - '''' Affiche les caractériques de l'objet''' - obj = get_object_or_404(Object, id=object_id) - return render(request, 'object/object_detail.html', {'object': obj}) -@login_required -def add_object(request): - """ - Envoie un formulaire pour poster un objet dans une communauté. - """ - if request.method == 'POST': - form = ObjectForm(request.POST) - if form.is_valid(): - # Ne pas sauvegarder immédiatement - object = form.save(commit=False) - - # Associer l'objet à l'utilisateur connecté - object.id_lender = request.user - - # Sauvegarder l'objet - object.save() - - # Optionnel : Redirection vers la page de gestion de la communauté - return redirect('add_object') - else: - form = ObjectForm() - - return render(request, 'object/add_object.html', {'form': form}) + @login_required def modify_object(request, object_id): - ''' Envoie un formulaire pour modifier les objets''' - obj = get_object_or_404(Object, id=object_id, id_lender=request.user) - if request.method == 'POST': - form = ObjectForm(request.POST, instance=obj) - if form.is_valid(): - form.save() - return redirect('object_list') - else: - form = ObjectForm(instance=obj) - return render(request, 'object/modify_object.html', {'form': form}) + # Récupérer l'objet UserObject pour l'utilisateur connecté + user_object = get_object_or_404(UserObject, id_lender=request.user, id=object_id) -@login_required -def delete_object(request, object_id): - ''' Supprime un objet sélectionné''' - obj = get_object_or_404(Object, id=object_id, id_lender=request.user) if request.method == 'POST': - obj.delete() + # Récupère la description envoyée via POST + description = request.POST.get('description') + + # Met à jour la description de l'objet UserObject + if description: + user_object.description = description + user_object.save() + + # Redirige l'utilisateur vers la page de confirmation ou une autre page après la mise à jour return redirect('object_list') - return render(request, 'object/delete_object.html', {'object': obj}) + return render(request, 'modify_object.html', {'user_object': user_object}) + +@login_required +def select_user_objects(request): + # Récupérer les objets sélectionnés par l'utilisateur + selected_objects = Selection.objects.filter(user=request.user).values_list('object_id', flat=True) + print(selected_objects) + + # Pré-remplir le formulaire avec ces sélections + initial_data = {'objects': Object.objects.filter(id__in=selected_objects)} + form = UserObjectSelectForm(None, initial=initial_data) + + if request.method == "POST": + form = UserObjectSelectForm(request.POST, initial=initial_data) + if form.is_valid(): + # Supprimer les anciennes sélections de l'utilisateur + Selection.objects.filter(user=request.user).delete() + UserObject.objects.filter(id_lender=request.user).delete() + + # Ajouter les nouvelles sélections + selected_objects = form.cleaned_data['objects'] + for object in selected_objects: + Selection.objects.create(user=request.user, object=object) + UserObject.objects.create(object=object, id_lender=request.user,is_borrowed=False) + + return redirect('object_list') # Recharger la page + + return render(request, 'select_user_objects.html', { + 'form': form + }) -- GitLab From 6ccf6693f9ba4be35a1a26ed298152c4684e0921 Mon Sep 17 00:00:00 2001 From: Godlewski Stanislas <stanislas.godlewski@student-cs.fr> Date: Thu, 21 Nov 2024 22:43:29 +0100 Subject: [PATCH 02/12] Version finale objets stan --- .../templates/object/select_user_objects.html | 57 +++++++++++++++++-- object/views.py | 26 ++++++++- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/object/templates/object/select_user_objects.html b/object/templates/object/select_user_objects.html index 4e4df06..f8a8806 100644 --- a/object/templates/object/select_user_objects.html +++ b/object/templates/object/select_user_objects.html @@ -2,15 +2,60 @@ {% load crispy_forms_tags %} -{% block content %} - <h1>Ajouter des objets que vous pouvez prêter</h1> - <form method="POST"> +{%block content%} +<head> +<style> + table { + width: 100%; + border-collapse: separate; /* Permet d'utiliser border-spacing */ + border-spacing: 10px; /* Ajoute de l'espace entre les colonnes */ + } + th, td { + border: 1px solid black; + vertical-align: top; /* Aligne tout en haut des colonnes */ + padding: 5px; + } + td { + vertical-align: top; /* Assure que les checkbox commencent en haut */ + } + label { + display: block; /* Assure un affichage en ligne séparée pour chaque objet */ + margin-bottom: 3px; /* Ajoute un espace entre les checkbox */ + } +</style> +</head> +<h1>Prêter des Objets</h1> + <form method="post"> {% csrf_token %} - {{ form|crispy}} - <button type="submit">Enregistrer la sélection</button> + <table> + <thead> + <tr> + {% for category_data in categories_with_objects %} + <th>{{ category_data.category.name }}</th> + {% endfor %} + </tr> + </thead> + <tbody> + <tr> + {% for category_data in categories_with_objects %} + <td> + {% for obj in category_data.objects %} + <label> + <input type="checkbox" name="objects" value="{{ obj.id }}" {% if obj.is_selected %}checked{% endif %}> + {{ obj.name }} + </label><br> + {% empty %} + Aucun objet dans cette catégorie. + {% endfor %} + </td> + {% endfor %} + </tr> + </tbody> + </table> + <button type="submit">Mettre à jour</button> </form> +{%endblock content%} -{% endblock content %} diff --git a/object/views.py b/object/views.py index 85c0c12..14ba77f 100644 --- a/object/views.py +++ b/object/views.py @@ -49,6 +49,9 @@ def modify_object(request, object_id): @login_required def select_user_objects(request): + + categories = ObjectCategory.objects.all() + # Récupérer les objets sélectionnés par l'utilisateur selected_objects = Selection.objects.filter(user=request.user).values_list('object_id', flat=True) print(selected_objects) @@ -71,7 +74,24 @@ def select_user_objects(request): UserObject.objects.create(object=object, id_lender=request.user,is_borrowed=False) return redirect('object_list') # Recharger la page - - return render(request, 'select_user_objects.html', { - 'form': form + + + categories_with_objects = [ + { + "category": category, + "objects": [ + { + "id": obj.id, + "name": obj.name, + "is_selected": obj.id in selected_objects, + } + for obj in category.object_set.all() + ], + } + for category in categories + ] + form = UserObjectSelectForm(initial={'objects': selected_objects}) + return render(request, "object/select_user_objects.html", { + "categories_with_objects": categories_with_objects, + "form": form, }) -- GitLab From b12018757c54c8b82d13b346505646a984778c3b Mon Sep 17 00:00:00 2001 From: Godlewski Stanislas <stanislas.godlewski@student-cs.fr> Date: Fri, 22 Nov 2024 08:47:34 +0100 Subject: [PATCH 03/12] Modification tests : coverage 81% --- Borrowing/tests.py | 23 ++++++++-------- object/tests.py | 65 +++++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Borrowing/tests.py b/Borrowing/tests.py index 44874ea..76acc89 100644 --- a/Borrowing/tests.py +++ b/Borrowing/tests.py @@ -1,7 +1,8 @@ from django.test import TestCase from django.urls import reverse from django.contrib.auth.models import User -from object.models import Object, ObjectCategory +from object.models import Object, ObjectCategory, UserObject +from object.scripts.script import create_objects_from_csv from Communities.models import Community, CommunityMembership from .models import BorrowRequest @@ -11,8 +12,6 @@ class BorrowingViewTests(TestCase): self.user = User.objects.create_user(username="testuser", password="password123") self.client.login(username="testuser", password="password123") - # Créer une catégorie d'objet - self.category = ObjectCategory.objects.create(name="Electronics") # Créer des objets pour les tests self.lender = User.objects.create_user(username="lender", password="password123") @@ -20,16 +19,18 @@ class BorrowingViewTests(TestCase): CommunityMembership.objects.create(user=self.user, community=self.community, role='member') CommunityMembership.objects.create(user=self.lender, community=self.community, role='admin') + + create_objects_from_csv() - self.object1 = Object.objects.create( - description="Laptop", - objectCategory=self.category, - id_lender=self.lender + self.object1 = UserObject.objects.create( + object=Object.objects.get(name="Bouilloire"), + id_lender=self.lender, + is_borrowed = False ) - self.object2 = Object.objects.create( - description="Tablet", - objectCategory=self.category, - id_lender=self.lender + self.object2 = UserObject.objects.create( + object=Object.objects.get(name="Cafetière"), + id_lender=self.lender, + is_borrowed = False ) def test_borrowing_page_loads(self): diff --git a/object/tests.py b/object/tests.py index ffccf47..6f4a705 100644 --- a/object/tests.py +++ b/object/tests.py @@ -1,27 +1,31 @@ from django.test import TestCase from django.urls import reverse from django.contrib.auth.models import User -from .models import Object, ObjectCategory +from .models import Object, ObjectCategory, UserObject, Selection +from .scripts.script import create_objects_from_csv class ObjectTests(TestCase): def setUp(self): # Créer un utilisateur de test self.user = User.objects.create_user(username='testuser', password='password') - # Créer une catégorie pour les objets - self.category = ObjectCategory.objects.create(name='Électronique') + create_objects_from_csv() + + self.category = ObjectCategory.objects.get(name="Jardinage") + self.obj_jardinage = Object.objects.get(name="Echelle") # Créer des objets de test - self.object1 = Object.objects.create( - description='Ordinateur', - objectCategory=self.category, - id_lender=self.user + self.object1 = UserObject.objects.create( + object=Object.objects.get(name="Cafetière"), + id_lender=self.user, + is_borrowed=False ) - self.object2 = Object.objects.create( - description='Smartphone', - objectCategory=self.category, - id_lender=self.user + self.object2 = UserObject.objects.create( + object=Object.objects.get(name="Bouilloire"), + id_lender=self.user, + is_borrowed=False ) + # Connecter l'utilisateur pour les tests nécessitant une authentification self.client.login(username='testuser', password='password') @@ -30,31 +34,38 @@ class ObjectTests(TestCase): """Tester si la liste des objets est correctement affichée.""" response = self.client.get(reverse('object_list')) self.assertEqual(response.status_code, 200) - self.assertContains(response, 'Ordinateur') - self.assertContains(response, 'Smartphone') + self.assertContains(response, 'Cafetière') + self.assertContains(response, 'Bouilloire') def test_add_object(self): + """Tester l'ajout d'un nouvel objet.""" - response = self.client.post(reverse('add_object'), { - 'description': 'Tablette', - 'objectCategory': self.category.id - }) - #self.assertEqual(response.status_code, 302) # Redirection après ajout Erreur !!!!!!! - #self.assertTrue(Object.objects.filter(description='Tablette').exists()) Erreur !!!!!!! + + self.url = reverse("select_user_objects") + # Données envoyées via le formulaire (sélectionne l'objet "Echelle") + data = { + "objects": [self.obj_jardinage.id], + } + + # Envoyer une requête POST pour sélectionner un objet + response = self.client.post(self.url, data) + + # Vérifier la redirection après soumission (assurez-vous que votre vue redirige comme attendu) + self.assertRedirects(response, '/object/') + # Vérifier que l'objet "Echelle" a été ajouté aux sélections + selection_exists = Selection.objects.filter( + user=self.user, + object=self.obj_jardinage + ).exists() + self.assertTrue(selection_exists, "L'objet 'Clé à molette' aurait dû être sélectionné.") def test_modify_object(self): """Tester la modification d'un objet existant.""" response = self.client.post(reverse('modify_object', args=[self.object1.id]), { - 'description': 'Ordinateur portable', - 'objectCategory': self.category.id + 'description': 'Il est très beau' }) #self.assertEqual(response.status_code, 302) # Redirection après modification Erreur !!!!!!! self.object1.refresh_from_db() - #self.assertEqual(self.object1.description, 'Ordinateur portable') Erreur !!!!!!! + self.assertEqual(self.object1.description, 'Il est très beau') - def test_delete_object(self): - """Tester la suppression d'un objet existant.""" - response = self.client.post(reverse('delete_object', args=[self.object2.id])) - #self.assertEqual(response.status_code, 302) # Redirection après suppression Erreur !!!!!!! - self.assertFalse(Object.objects.filter(id=self.object2.id).exists()) -- GitLab From ca4e6e667d43d51537ec55a46f4bafa2d209b478 Mon Sep 17 00:00:00 2001 From: Godlewski Stanislas <stanislas.godlewski@student-cs.fr> Date: Fri, 22 Nov 2024 08:59:16 +0100 Subject: [PATCH 04/12] Correctif commentaires --- object/tests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/object/tests.py b/object/tests.py index 6f4a705..7de1be1 100644 --- a/object/tests.py +++ b/object/tests.py @@ -50,7 +50,7 @@ class ObjectTests(TestCase): # Envoyer une requête POST pour sélectionner un objet response = self.client.post(self.url, data) - # Vérifier la redirection après soumission (assurez-vous que votre vue redirige comme attendu) + # Vérifier la redirection après soumission self.assertRedirects(response, '/object/') # Vérifier que l'objet "Echelle" a été ajouté aux sélections selection_exists = Selection.objects.filter( @@ -64,7 +64,6 @@ class ObjectTests(TestCase): response = self.client.post(reverse('modify_object', args=[self.object1.id]), { 'description': 'Il est très beau' }) - #self.assertEqual(response.status_code, 302) # Redirection après modification Erreur !!!!!!! self.object1.refresh_from_db() self.assertEqual(self.object1.description, 'Il est très beau') -- GitLab From 529b37738fd30ee8eca8c34ecab66b29c59656c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me?= <come.lacouxfauvet@student-cs.fr> Date: Fri, 22 Nov 2024 09:57:25 +0100 Subject: [PATCH 05/12] Style version de Stan --- object/templates/object/object_list.html | 2 +- object/templates/object/select_user_objects.html | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/object/templates/object/object_list.html b/object/templates/object/object_list.html index 6449548..42ffec8 100644 --- a/object/templates/object/object_list.html +++ b/object/templates/object/object_list.html @@ -15,7 +15,7 @@ Gérer mes sollicitations </a> -<table border="1"> +<table border="1" class="table"> <thead> <tr> <th>Name</th> diff --git a/object/templates/object/select_user_objects.html b/object/templates/object/select_user_objects.html index f8a8806..2909f75 100644 --- a/object/templates/object/select_user_objects.html +++ b/object/templates/object/select_user_objects.html @@ -11,11 +11,6 @@ border-collapse: separate; /* Permet d'utiliser border-spacing */ border-spacing: 10px; /* Ajoute de l'espace entre les colonnes */ } - th, td { - border: 1px solid black; - vertical-align: top; /* Aligne tout en haut des colonnes */ - padding: 5px; - } td { vertical-align: top; /* Assure que les checkbox commencent en haut */ } @@ -23,16 +18,17 @@ display: block; /* Assure un affichage en ligne séparée pour chaque objet */ margin-bottom: 3px; /* Ajoute un espace entre les checkbox */ } + </style> </head> <h1>Prêter des Objets</h1> <form method="post"> {% csrf_token %} - <table> + <table class="table" border="1"> <thead> <tr> {% for category_data in categories_with_objects %} - <th>{{ category_data.category.name }}</th> + <th scope="col">{{ category_data.category.name }}</th> {% endfor %} </tr> </thead> @@ -53,7 +49,7 @@ </tr> </tbody> </table> - <button type="submit">Mettre à jour</button> + <button class="btn btn-success mb-3" type="submit">Mettre à jour</button> </form> {%endblock content%} -- GitLab From 3f32c8bce8f1136c71c469f08e84057402a56770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me?= <come.lacouxfauvet@student-cs.fr> Date: Fri, 22 Nov 2024 09:59:40 +0100 Subject: [PATCH 06/12] Dernier commit --- Borrowing/templates/index.html | 1 - Communities/models.py | 3 --- 2 files changed, 4 deletions(-) diff --git a/Borrowing/templates/index.html b/Borrowing/templates/index.html index ee875b8..bfe9d9e 100644 --- a/Borrowing/templates/index.html +++ b/Borrowing/templates/index.html @@ -29,7 +29,6 @@ <h1 class="display-3 fw-bolder mb-5"><span class="gradient-text d-inline">Le site de prêt entre voisins</span></h1> <div class="d-grid gap-3 d-sm-flex justify-content-sm-center justify-content-xxl-start mb-3"> <a class="btn btn-primary btn-lg px-5 py-3 me-sm-3 fs-6 fw-bolder" href="/community/">Trouver la communauté la plus proche</a> - <a class="btn btn-outline-dark btn-lg px-5 py-3 fs-6 fw-bolder" href="/avenir/">Avenir</a> </div> </div> </div> diff --git a/Communities/models.py b/Communities/models.py index 853faf0..de9ce7d 100644 --- a/Communities/models.py +++ b/Communities/models.py @@ -22,9 +22,6 @@ class Community(models.Model): ''' Retourne tous les objets prêtés par des membres de cette communauté. ''' - # Utiliser une requête différée pour récupérer les membres de la communauté - from .models import CommunityMembership, UserObject - # Obtenir les utilisateurs membres de la communauté member_ids = CommunityMembership.objects.filter(community=self).values_list('user_id', flat=True) -- GitLab From 9b34c3605ed42de0c8016e0317471202e5f521c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me?= <come.lacouxfauvet@student-cs.fr> Date: Fri, 22 Nov 2024 09:08:30 +0100 Subject: [PATCH 07/12] =?UTF-8?q?Fin=20du=20style,=20r=C3=A9paration=20de?= =?UTF-8?q?=20la=20navbar=20etc,=20unit=C3=A9=20stylistique?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Borrowing/templates/Borrowing/base.html | 14 +- Borrowing/templates/index2.html | 112 ------------ Borrowing/templates/index4.html | 159 ------------------ .../templates/Communities/admin_board.html | 6 +- .../Communities/list_objects_community.html | 2 +- .../templates/Communities/view_requests.html | 2 +- object/templates/object/object_detail.html | 6 +- 7 files changed, 21 insertions(+), 280 deletions(-) delete mode 100644 Borrowing/templates/index2.html delete mode 100644 Borrowing/templates/index4.html diff --git a/Borrowing/templates/Borrowing/base.html b/Borrowing/templates/Borrowing/base.html index 0073172..fb9631c 100644 --- a/Borrowing/templates/Borrowing/base.html +++ b/Borrowing/templates/Borrowing/base.html @@ -22,7 +22,7 @@ <style> body { background-color: #e9ffea; - padding-top: 15vh !important; + padding-top: var(--navbar-height); } </style> <main class="flex-shrink-0"> @@ -117,5 +117,17 @@ <script src="{% static 'js/bootstrap.bundle.min.js' %}"></script> <!-- Core theme JS--> <script src="{% static 'js/scripts.js' %}"></script> + <script> + // Fonction pour ajuster dynamiquement le padding-top du body + function adjustBodyPadding() { + const navbar = document.querySelector('.navbar'); + const navbarHeight = navbar.offsetHeight; // Hauteur réelle de la navbar + document.documentElement.style.setProperty('--navbar-height', `${navbarHeight}px`); + } + + // Ajuste le padding au chargement et au redimensionnement + window.addEventListener('load', adjustBodyPadding); + window.addEventListener('resize', adjustBodyPadding); + </script> </body> </html> diff --git a/Borrowing/templates/index2.html b/Borrowing/templates/index2.html deleted file mode 100644 index 8680647..0000000 --- a/Borrowing/templates/index2.html +++ /dev/null @@ -1,112 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - {% load static %} - <link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" type="text/css"> - <meta name="description" content="The index page of CommunityShare.fr"> - <title>CommunityShare</title> -</head> -<body> - <style> - body { - background-color: #e9ffea; - } - </style> - <nav class="navbar bg-body-c" style="background-color: #349e5b;"> - <div class="container-fluid"> - <span class="navbar-brand mb-0 h1">CommunityShare</span> - <ul class="nav nav-underline justify-content-end"> - <li class="nav-item"> - <a class="nav-link active" href="#">Accueil</a> - </li> - <li> - <a class="nav-link link-info" href="/community/">Communautés</a> - </li> - <li> - <a class="nav-link link-info" href="/user/">Mon compte</a> - </li> - </ul> - </div> - </nav> - <div class="container"> - <main> - <div class="container"> - <h1 class="text-center my-4">Découvrir CommunityShare</h2> - <p> - CommunityShare est une plateforme de partage d'objets entre particuliers et associations. - </p> - <p> - Découvrir les <a class="link-underline link-underline-opacity-0" href="/community/">communautés</a> - </p> - </div> - </main> - </div> - <footer class="bg-body-tertiary text-center"> - <div class="container p-4"> - <section class=""> - <div class="row"> - <div class="col-lg-4 col-md-6 mb-4 mb-md-0"> - <h5 class="text">Liens</h5> - - <ul class="list-unstyled mb-0"> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/">Accueil</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/user/">Mon compte</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/community/">Communautés</a> - </li> - </ul> - </div> - <div class="col-lg-4 col-md-6 mb-4 mb-md-0"> - <h5 class="text">Emprunter, prêter</h5> - - <ul class="list-unstyled mb-0"> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/">Dashboard</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/borrow">Emprunter</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/borrow_request">Demandes de prêts</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/my_requests">Mes demandes</a> - </li> - </ul> - </div> - <div class="col-lg-4 col-md-6 mb-4 mb-md-0"> - <h5 class="text">Links</h5> - - <ul class="list-unstyled mb-0"> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 1</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 2</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 3</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 4</a> - </li> - </ul> - </div> - </div> - </section> - </div> - <div class="text-center p-3" style="background-color: rgba(0, 0, 0, 0.05);"> - © 2024 - <a class="text-reset fw-bold" href="/">CommunityShare.fr</a> - Tous droits réservés. - </div> - </footer> - <script src="{% static 'js/bootstrap.bundle.min.js' %}"></script> -</body> -</html> \ No newline at end of file diff --git a/Borrowing/templates/index4.html b/Borrowing/templates/index4.html deleted file mode 100644 index 4139838..0000000 --- a/Borrowing/templates/index4.html +++ /dev/null @@ -1,159 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> - <meta name="description" content="" /> - <meta name="author" content="" /> - <title>CommunityShare</title> - <!--Loading static files--> - {% load static %} - <!-- Favicon--> - <link rel="icon" type="image/x-icon" href="{% static 'assets/favicon.ico' %}" /> - <!-- Custom Google font--> - <link rel="preconnect" href="https://fonts.googleapis.com" /> - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> - <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet" /> - <!-- Bootstrap icons--> - <link href="{% static 'icons/font/bootstrap-icons.css' %}" rel="stylesheet" /> - <!-- Core theme CSS (includes Bootstrap)--> - <link href="{% static 'css/styles.css' %}" rel="stylesheet" type="text/css"> - - </head> - <body class="d-flex flex-column h-100"> - <style> - body { - background-color: #e9ffea; - } - </style> - <main class="flex-shrink-0"> - <!-- Navigation--> - <nav class="navbar navbar-expand-lg navbar-light py-3" style="background-color: #349e5b;"> - <div class="container px-5"> - <a class="navbar-brand" href="/"><span class="fw-bolder text-light">CommunityShare</span></a> - <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button> - <div class="collapse navbar-collapse" id="navbarSupportedContent"> - <ul class="navbar-nav ms-auto mb-2 mb-lg-0 small fw-bolder"> - <li class="nav-item"><a class="nav-link" href="/">Accueil</a></li> - <li class="nav-item"><a class="nav-link" href="/community/">Mes communautés</a></li> - <li class="nav-item"><a class="nav-link" href="/user/">Mon profil</a></li> - <li class="nav-item"><a class="nav-link" href="/user/logout/">Se déconnecter</a></li> - </ul> - </div> - </div> - </nav> - <!-- Header--> - <header class="py-5"> - <div class="container px-5 pb-5"> - <div class="row gx-5 align-items-center"> - <div class="col-xxl-5"> - <!-- Header text content--> - <div class="text-center text-xxl-start"> - <div class="badge bg-gradient-primary-to-secondary text-white mb-4"><div class="text-uppercase">Entraide · Partage · Voisinage</div></div> - <div class="fs-3 fw-light text-muted">I can help your business to</div> - <h1 class="display-3 fw-bolder mb-5"><span class="text-gradient d-inline">Get online and grow fast</span></h1> - <div class="d-grid gap-3 d-sm-flex justify-content-sm-center justify-content-xxl-start mb-3"> - <a class="btn btn-primary btn-lg px-5 py-3 me-sm-3 fs-6 fw-bolder" href="/community/">Trouver la communauté la plus proche</a> - <a class="btn btn-outline-dark btn-lg px-5 py-3 fs-6 fw-bolder" href="projects.html">Projects</a> - </div> - </div> - </div> - </div> - </div> - </header> - <!-- About Section--> - <section class="bg-light py-5"> - <div class="container px-5"> - <div class="row gx-5 justify-content-center"> - <div class="col-xxl-8"> - <div class="text-center my-5"> - <h2 class="display-5 fw-bolder"><span class="text-gradient d-inline">Le projet</span></h2> - <p class="lead fw-light mb-4">CommunityShare est un site de partage d'objets entre particuliers au sein de communautés.</p> - <p class="text-muted">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit dolorum itaque qui unde quisquam consequatur autem. Eveniet quasi nobis aliquid cumque officiis sed rem iure ipsa! Praesentium ratione atque dolorem?</p> - <div class="d-flex justify-content-center fs-2 gap-4"> - <a class="text-gradient" href="#!"><i class="bi bi-twitter"></i></a> - <a class="text-gradient" href="#!"><i class="bi bi-linkedin"></i></a> - <a class="text-gradient" href="https://gitlab-cw4.centralesupelec.fr/chakib.lahrach/communityshare"><i class="bi bi-gitlab"></i></a> - </div> - </div> - </div> - </div> - </div> - </section> - </main> - <!-- Footer--> - <footer class="bg-white py-4 mt-auto"> - <div class="container px-5"> - <section class=""> - <div class="row"> - <div class="col-lg-5 col-md-6 mb-4 mb-md-0"> - <h5 class="text">Liens</h5> - - <ul class="list-unstyled mb-0"> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/">Accueil</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/user/">Mon profil</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/community/">Mes communautés</a> - </li> - </ul> - </div> - <div class="col-lg-5 col-md-6 mb-4 mb-md-0"> - <h5 class="text">Emprunter, prêter</h5> - - <ul class="list-unstyled mb-0"> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/">Dashboard</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/borrow">Emprunter</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/borrow_request">Demandes de prêts</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="/borrowing/my_requests">Mes demandes</a> - </li> - </ul> - </div> - <!--<div class="col-lg-5 col-md-6 mb-4 mb-md-0"> - <h5 class="text">Links</h5> - - <ul class="list-unstyled mb-0"> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 1</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 2</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 3</a> - </li> - <li> - <a class="link-dark link-offset-3-hover link-underline link-underline-opacity-0 link-underline-opacity-75-hover" href="#!">Link 4</a> - </li> - </ul> - </div>--> - </div> - </section> - <div class="row align-items-center justify-content-between flex-column flex-sm-row"> - <div class="col-auto"><div class="small m-0">© CommunityShare 2024</div></div> - <div class="col-auto"> - <a class="small" href="#!">Privacy</a> - <span class="mx-1">·</span> - <a class="small" href="#!">Terms</a> - <span class="mx-1">·</span> - <a class="small" href="#!">Contact</a> - </div> - </div> - </div> - </footer> - <!-- Bootstrap core JS--> - <script src="{% static 'js/bootstrap.bundle.min.js' %}"></script> - <!-- Core theme JS--> - <script src="{% static 'js/scripts.js' %}"></script> - </body> -</html> diff --git a/Communities/templates/Communities/admin_board.html b/Communities/templates/Communities/admin_board.html index 4e86469..c3d7249 100644 --- a/Communities/templates/Communities/admin_board.html +++ b/Communities/templates/Communities/admin_board.html @@ -9,14 +9,14 @@ <p> Vous gérez également la communauté parent : <strong>{{ community.parent.name }}</strong>. </p> - <a href="{% url 'admin_board' community.parent.id %}" class="btn btn-secondary"> + <a href="{% url 'admin_board' community.parent.id %}" class="btn btn-primary"> Administrer la communauté parent </a> {% endif %} <h2>Gérer les demandes</h2> -<a href="{% url 'view_requests' community.id %}" class="btn btn-primary">Voir les demandes</a> +<a href="{% url 'view_requests' community.id %}" class="btn btn-success">Voir les demandes</a> <h2>Sous-communautés</h2> <ul> @@ -40,7 +40,7 @@ <!--Bouton de la liste des membres--> <h2>Membres</h2> -<a href="{% url 'list_member_admin' community.id %}" class = "btn btn-primary">Gérer les membres</a> +<a href="{% url 'list_member_admin' community.id %}" class = "btn btn-success">Gérer les membres</a> <!-- Bouton de suppression de la communauté --> diff --git a/Communities/templates/Communities/list_objects_community.html b/Communities/templates/Communities/list_objects_community.html index 357726f..ca8025d 100644 --- a/Communities/templates/Communities/list_objects_community.html +++ b/Communities/templates/Communities/list_objects_community.html @@ -5,7 +5,7 @@ <h1>Liste des objets disponibles dans {{ community.name }}</h1> <!-- Bouton pour retourner au user board --> -<a href="{% url 'user_board' %}" class="btn btn-secondary mb-3">Retour au tableau utilisateur</a> +<a href="{% url 'user_board' %}" class="btn btn-primary mb-3">Retour au tableau utilisateur</a> <!-- Bouton Pour Faire une demande --> <a href="{% url 'borrow' %}" class="btn btn-success mb-3"> diff --git a/Communities/templates/Communities/view_requests.html b/Communities/templates/Communities/view_requests.html index 3702b01..a2dc547 100644 --- a/Communities/templates/Communities/view_requests.html +++ b/Communities/templates/Communities/view_requests.html @@ -32,5 +32,5 @@ {% else %} <p>Aucune demande en attente.</p> {% endif %} -<a href="{% url 'admin_board' community.id %}" class="btn btn-secondary">Retour au tableau de bord</a> +<a href="{% url 'admin_board' community.id %}" class="btn btn-primary">Retour au tableau de bord</a> {% endblock %} diff --git a/object/templates/object/object_detail.html b/object/templates/object/object_detail.html index fa2675e..e25918a 100644 --- a/object/templates/object/object_detail.html +++ b/object/templates/object/object_detail.html @@ -11,9 +11,9 @@ </ul> <div> - <a href="{% url 'modify_object' object.id %}">Modifier</a> | - <a href="{% url 'delete_object' object.id %}" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet objet ?')">Supprimer</a> + <a href="{% url 'modify_object' object.id %}" class="btn btn-primary">Modifier</a> | + <a href="{% url 'delete_object' object.id %}" class="btn btn-danger" onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet objet ?')">Supprimer</a> </div> -<a href="{% url 'object_list' %}">Retour à la liste</a> +<a href="{% url 'object_list' %}" class="btn btn-success">Retour à la liste</a> {% endblock %} -- GitLab From ab95f90a19f97392a22c45b570b1efe305df0ba4 Mon Sep 17 00:00:00 2001 From: Godlewski Stanislas <stanislas.godlewski@student-cs.fr> Date: Thu, 21 Nov 2024 18:13:31 +0100 Subject: [PATCH 08/12] Version fonctionnelle objets --- object/templates/object/object_list.html | 2 +- object/views.py | 47 ++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/object/templates/object/object_list.html b/object/templates/object/object_list.html index 42ffec8..6449548 100644 --- a/object/templates/object/object_list.html +++ b/object/templates/object/object_list.html @@ -15,7 +15,7 @@ Gérer mes sollicitations </a> -<table border="1" class="table"> +<table border="1"> <thead> <tr> <th>Name</th> diff --git a/object/views.py b/object/views.py index 14ba77f..f6b76d0 100644 --- a/object/views.py +++ b/object/views.py @@ -1,6 +1,8 @@ from django.shortcuts import render, redirect, get_object_or_404 from .forms import ObjectForm, UserObjectSelectForm from .models import Object, UserObject, ObjectCategory, Selection +from .forms import ObjectForm, UserObjectSelectForm +from .models import Object, UserObject, ObjectCategory, Selection from django.contrib.auth.decorators import login_required ''' @@ -23,16 +25,22 @@ Structure la page en : def object_list(request): '''Interface qui propose tous les objets que l'utilisateur peut prêter''' objects = UserObject.objects.filter(id_lender=request.user) + objects = UserObject.objects.filter(id_lender=request.user) return render(request, 'object/object_list.html', {'objects': objects}) + + @login_required def modify_object(request, object_id): # Récupérer l'objet UserObject pour l'utilisateur connecté user_object = get_object_or_404(UserObject, id_lender=request.user, id=object_id) + # Récupérer l'objet UserObject pour l'utilisateur connecté + user_object = get_object_or_404(UserObject, id_lender=request.user, id=object_id) + if request.method == 'POST': # Récupère la description envoyée via POST description = request.POST.get('description') @@ -45,9 +53,48 @@ def modify_object(request, object_id): # Redirige l'utilisateur vers la page de confirmation ou une autre page après la mise à jour return redirect('object_list') + return render(request, 'modify_object.html', {'user_object': user_object}) + # Récupère la description envoyée via POST + description = request.POST.get('description') + + # Met à jour la description de l'objet UserObject + if description: + user_object.description = description + user_object.save() + + # Redirige l'utilisateur vers la page de confirmation ou une autre page après la mise à jour + return redirect('object_list') + return render(request, 'modify_object.html', {'user_object': user_object}) @login_required +def select_user_objects(request): + # Récupérer les objets sélectionnés par l'utilisateur + selected_objects = Selection.objects.filter(user=request.user).values_list('object_id', flat=True) + print(selected_objects) + + # Pré-remplir le formulaire avec ces sélections + initial_data = {'objects': Object.objects.filter(id__in=selected_objects)} + form = UserObjectSelectForm(None, initial=initial_data) + + if request.method == "POST": + form = UserObjectSelectForm(request.POST, initial=initial_data) + if form.is_valid(): + # Supprimer les anciennes sélections de l'utilisateur + Selection.objects.filter(user=request.user).delete() + UserObject.objects.filter(id_lender=request.user).delete() + + # Ajouter les nouvelles sélections + selected_objects = form.cleaned_data['objects'] + for object in selected_objects: + Selection.objects.create(user=request.user, object=object) + UserObject.objects.create(object=object, id_lender=request.user,is_borrowed=False) + + return redirect('object_list') # Recharger la page + + return render(request, 'select_user_objects.html', { + 'form': form + }) def select_user_objects(request): categories = ObjectCategory.objects.all() -- GitLab From e2896c188ecd1be4374f2530dfaad6cd638739f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me?= <come.lacouxfauvet@student-cs.fr> Date: Fri, 22 Nov 2024 10:09:05 +0100 Subject: [PATCH 09/12] le vrai dernier commit --- object/templates/object/object_list.html | 4 ++-- object/views.py | 11 ----------- 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/object/templates/object/object_list.html b/object/templates/object/object_list.html index 6449548..abd8047 100644 --- a/object/templates/object/object_list.html +++ b/object/templates/object/object_list.html @@ -15,7 +15,7 @@ Gérer mes sollicitations </a> -<table border="1"> +<table border="1" class="table"> <thead> <tr> <th>Name</th> @@ -33,7 +33,7 @@ {{obj.object.category.name}} </td> <td> - <a href="{% url 'modify_object' obj.id %}">Ajouter une description</a> | + <a href="{% url 'modify_object' obj.id %}">Ajouter une description</a> </td> diff --git a/object/views.py b/object/views.py index f6b76d0..4a5ef19 100644 --- a/object/views.py +++ b/object/views.py @@ -54,18 +54,7 @@ def modify_object(request, object_id): return redirect('object_list') return render(request, 'modify_object.html', {'user_object': user_object}) - # Récupère la description envoyée via POST - description = request.POST.get('description') - # Met à jour la description de l'objet UserObject - if description: - user_object.description = description - user_object.save() - - # Redirige l'utilisateur vers la page de confirmation ou une autre page après la mise à jour - return redirect('object_list') - - return render(request, 'modify_object.html', {'user_object': user_object}) @login_required def select_user_objects(request): -- GitLab From b5725e52390dbf1a29ab57b94289f8ce587e74d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me?= <come.lacouxfauvet@student-cs.fr> Date: Fri, 22 Nov 2024 10:10:41 +0100 Subject: [PATCH 10/12] le vrai dernier commit2 --- object/templates/object/modify_object.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/object/templates/object/modify_object.html b/object/templates/object/modify_object.html index e3fdbfb..2a88eb6 100644 --- a/object/templates/object/modify_object.html +++ b/object/templates/object/modify_object.html @@ -6,7 +6,7 @@ <form method="POST"> {% csrf_token %} <textarea name="description" rows="4" cols="50" placeholder="Entrez une description pour cet objet">{{ user_object.description }}</textarea> - <button type="submit">Enregistrer</button> + <button type="submit" class="btn btn-success">Enregistrer</button> </form> <p><a href="{% url 'object_list' %}">Retour aux objets</a></p> -- GitLab From f38475acd9c7bc6c59666e2795077ea88b64c76a Mon Sep 17 00:00:00 2001 From: Van Hecke Adiel <adiel.van-hecke@student-cs.fr> Date: Fri, 22 Nov 2024 10:08:20 +0100 Subject: [PATCH 11/12] My request's button --- Borrowing/templates/Borrowing/borrowing.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Borrowing/templates/Borrowing/borrowing.html b/Borrowing/templates/Borrowing/borrowing.html index fdb7e16..cf3ed62 100644 --- a/Borrowing/templates/Borrowing/borrowing.html +++ b/Borrowing/templates/Borrowing/borrowing.html @@ -18,4 +18,8 @@ </ul> <p>{{message}}</p> + <!-- Bouton Gérer mes demandes --> + <a href="{% url 'my_requests' %}" class="btn btn-success mb-3"> + Mes demandes + </a> {% endblock content %} \ No newline at end of file -- GitLab From e2992519208e88aaf353c6bb0afb55315db4dbc8 Mon Sep 17 00:00:00 2001 From: Van Hecke Adiel <adiel.van-hecke@student-cs.fr> Date: Fri, 22 Nov 2024 10:19:50 +0100 Subject: [PATCH 12/12] bugForm --- user/forms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user/forms.py b/user/forms.py index d0bdefd..fa29bf9 100644 --- a/user/forms.py +++ b/user/forms.py @@ -23,5 +23,5 @@ class User_modify(forms.Form): first_name = forms.CharField(label="first_name", max_length=100) last_name = forms.CharField(label="last_name", max_length=100) email = forms.CharField(label="email", max_length=100) - phone = forms.CharField(label="phone",max_length=15) - address = forms.CharField(label="address") \ No newline at end of file + phone = forms.CharField(label="phone",max_length=15, required = False) + address = forms.CharField(label="address", required = False) \ No newline at end of file -- GitLab