diff --git a/LITReview/LITReview/urls.py b/LITReview/LITReview/urls.py index ca1d974..dfaa3f8 100644 --- a/LITReview/LITReview/urls.py +++ b/LITReview/LITReview/urls.py @@ -25,10 +25,10 @@ import authentication.views, reviews.views urlpatterns = [ path('admin/', admin.site.urls), path('home/', reviews.views.home, name='home'), -# path('', LoginView.as_view( - path('', authentication.views.login_page, name='login'), -# template_name='authentication/login.html', -# redirect_authenticated_user=True), name='login'), + path('', LoginView.as_view( +# path('', authentication.views.login_page, name='login'), + template_name='authentication/login.html', + redirect_authenticated_user=True), name='login'), path('pwd-change/', PasswordChangeView.as_view( template_name='authentication/pwd_change.html'), name='pwd-change'), path('pwd-change-done/', PasswordChangeDoneView.as_view( @@ -43,6 +43,7 @@ urlpatterns = [ path('ticket//', reviews.views.ticket, name='ticket-detail'), path('ticket//update/', reviews.views.update_ticket, name='ticket-update'), path('ticket//delete/', reviews.views.delete_ticket, name='ticket-delete'), + path('ticket//review/', reviews.views.ticket_review, name='review-ticket'), path('review//', reviews.views.review, name='review-detail'), path('review//update/', reviews.views.update_review, name='review-update'), path('review//delete/', reviews.views.delete_review, name='review-delete'), diff --git a/LITReview/media/uploads/Capture_décran_du_2025-02-06_09-57-33.png b/LITReview/media/uploads/Capture_décran_du_2025-02-06_09-57-33.png new file mode 100644 index 0000000..59ebd6e Binary files /dev/null and b/LITReview/media/uploads/Capture_décran_du_2025-02-06_09-57-33.png differ diff --git a/LITReview/media/uploads/Capture_décran_du_2025-03-11_18-11-09.png b/LITReview/media/uploads/Capture_décran_du_2025-03-11_18-11-09.png new file mode 100644 index 0000000..dc1ba08 Binary files /dev/null and b/LITReview/media/uploads/Capture_décran_du_2025-03-11_18-11-09.png differ diff --git a/LITReview/media/uploads/Capture_décran_du_2025-04-29_15-44-14.png b/LITReview/media/uploads/Capture_décran_du_2025-04-29_15-44-14.png new file mode 100644 index 0000000..5bda68c Binary files /dev/null and b/LITReview/media/uploads/Capture_décran_du_2025-04-29_15-44-14.png differ diff --git a/LITReview/media/uploads/HowCompaniesShipCode.gif b/LITReview/media/uploads/HowCompaniesShipCode.gif new file mode 100644 index 0000000..a9f1143 Binary files /dev/null and b/LITReview/media/uploads/HowCompaniesShipCode.gif differ diff --git a/LITReview/media/uploads/bergson.jpg b/LITReview/media/uploads/bergson.jpg new file mode 100644 index 0000000..f6f1ded Binary files /dev/null and b/LITReview/media/uploads/bergson.jpg differ diff --git a/LITReview/media/uploads/crusoe.jpg b/LITReview/media/uploads/crusoe.jpg index e2ceb47..f0937de 100644 Binary files a/LITReview/media/uploads/crusoe.jpg and b/LITReview/media/uploads/crusoe.jpg differ diff --git a/LITReview/media/uploads/git.jpeg b/LITReview/media/uploads/git.jpeg deleted file mode 100644 index 1197046..0000000 Binary files a/LITReview/media/uploads/git.jpeg and /dev/null differ diff --git a/LITReview/media/uploads/punch.jpeg b/LITReview/media/uploads/punch.jpeg new file mode 100644 index 0000000..09d8baa Binary files /dev/null and b/LITReview/media/uploads/punch.jpeg differ diff --git a/LITReview/media/uploads/world.jpg b/LITReview/media/uploads/world.jpg new file mode 100644 index 0000000..dc6e4a4 Binary files /dev/null and b/LITReview/media/uploads/world.jpg differ diff --git a/LITReview/media/uploads/world_yMlrjFr.jpg b/LITReview/media/uploads/world_yMlrjFr.jpg new file mode 100644 index 0000000..10b622f Binary files /dev/null and b/LITReview/media/uploads/world_yMlrjFr.jpg differ diff --git a/LITReview/reviews/forms.py b/LITReview/reviews/forms.py index 5561049..4f0ac47 100644 --- a/LITReview/reviews/forms.py +++ b/LITReview/reviews/forms.py @@ -5,13 +5,14 @@ from . import models class TicketForm(forms.ModelForm): class Meta: model = models.Ticket - fields = ['title', 'body', 'image'] + fields = ['title', 'desc', 'image'] class ReviewForm(forms.ModelForm): - CHOICES = [0, 1, 2, 3, 4, 5] + CHOICES = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5} rating = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES) class Meta: model = models.Review - fields = ['headline', 'body'] + fields = ['headline', 'rating', 'comment'] + diff --git a/LITReview/reviews/migrations/0003_alter_ticket_image.py b/LITReview/reviews/migrations/0003_alter_ticket_image.py new file mode 100644 index 0000000..86539a5 --- /dev/null +++ b/LITReview/reviews/migrations/0003_alter_ticket_image.py @@ -0,0 +1,18 @@ +# Generated by Django 5.2 on 2025-04-26 12:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reviews', '0002_userfollows_followed_user_userfollows_user_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='ticket', + name='image', + field=models.ImageField(upload_to=''), + ), + ] diff --git a/LITReview/reviews/migrations/0004_rename_body_ticket_desc_remove_review_body_and_more.py b/LITReview/reviews/migrations/0004_rename_body_ticket_desc_remove_review_body_and_more.py new file mode 100644 index 0000000..459e469 --- /dev/null +++ b/LITReview/reviews/migrations/0004_rename_body_ticket_desc_remove_review_body_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 5.2 on 2025-05-01 12:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reviews', '0003_alter_ticket_image'), + ] + + operations = [ + migrations.RenameField( + model_name='ticket', + old_name='body', + new_name='desc', + ), + migrations.RemoveField( + model_name='review', + name='body', + ), + migrations.AddField( + model_name='review', + name='comment', + field=models.CharField(blank=True, max_length=8192, verbose_name='commentaire'), + ), + ] diff --git a/LITReview/reviews/migrations/0005_userfollows_starting_date.py b/LITReview/reviews/migrations/0005_userfollows_starting_date.py new file mode 100644 index 0000000..1bda933 --- /dev/null +++ b/LITReview/reviews/migrations/0005_userfollows_starting_date.py @@ -0,0 +1,20 @@ +# Generated by Django 5.2 on 2025-05-01 17:23 + +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('reviews', '0004_rename_body_ticket_desc_remove_review_body_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='userfollows', + name='starting_date', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + ] diff --git a/LITReview/reviews/models.py b/LITReview/reviews/models.py index 99af0a5..4d9ba9e 100644 --- a/LITReview/reviews/models.py +++ b/LITReview/reviews/models.py @@ -1,18 +1,30 @@ from django.core.validators import MinValueValidator, MaxValueValidator from django.conf import settings from django.db import models +from PIL import Image class Ticket(models.Model): # Your Ticket model definition goes here title = models.CharField("Titre", max_length=100) topic = models.CharField(max_length=100) - body = models.CharField("Description", max_length=8192) + desc = models.CharField("Description", max_length=8192) user = models.ForeignKey( to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE) - image = models.ImageField(upload_to="uploads/") + image = models.ImageField() time_created = models.DateTimeField(auto_now_add=True) + review = models.ForeignKey(to=Review, on_delete=models.SET_NULL) + IMAGE_SIZE = (400, 400) + + def resize_image(self): + image = Image.open(self.image) + image.thumbnail(self.IMAGE_SIZE) + image.save(self.image.path) + + def save(self, *args, **kwargs): + super().save(*args, **kwargs) + self.resize_image() class Review(models.Model): @@ -21,7 +33,7 @@ class Review(models.Model): # validates that rating must be between 0 and 5 validators=[MinValueValidator(0), MaxValueValidator(5)]) headline = models.CharField("titre", max_length=128) - body = models.CharField("description", max_length=8192, blank=True) + comment = models.CharField("commentaire", max_length=8192, blank=True) user = models.ForeignKey( to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE) time_created = models.DateTimeField(auto_now_add=True) @@ -31,6 +43,7 @@ class UserFollows(models.Model): # Your UserFollows model definition goes here user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="following", null=True) followed_user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="followed", null=True) + starting_date = models.DateTimeField(auto_now_add=True) class Meta: # ensures we don't get multiple UserFollows instances diff --git a/LITReview/reviews/templates/reviews/flux.html b/LITReview/reviews/templates/reviews/flux.html index db4e9f7..f962588 100644 --- a/LITReview/reviews/templates/reviews/flux.html +++ b/LITReview/reviews/templates/reviews/flux.html @@ -1,12 +1,23 @@ {% extends 'base.html' %} -{% block nav %} - -{% endblock %} + {% block content %} -

Flux

-{% endblock %} + +
+
+
+

FLux

+
+
+
+ {% for ticket in tickets %} + {% include 'reviews/ticket_detail.html' %} + +
+ {% endfor %} +
+ + + +{% endblock %} \ No newline at end of file diff --git a/LITReview/reviews/templates/reviews/home.html b/LITReview/reviews/templates/reviews/home.html index 60e63d1..10aad2d 100644 --- a/LITReview/reviews/templates/reviews/home.html +++ b/LITReview/reviews/templates/reviews/home.html @@ -16,8 +16,16 @@
- {% for ticket in tickets %} - {% include 'reviews/ticket_detail.html' %} + {% for ticket in tickets %} + {% include 'reviews/ticket_detail.html' %} +
+ {% if ticket.review is not True %} + + {% endif %} +
+
{% endfor %} diff --git a/LITReview/reviews/templates/reviews/posts.html b/LITReview/reviews/templates/reviews/posts.html index 1d79920..6a60b64 100644 --- a/LITReview/reviews/templates/reviews/posts.html +++ b/LITReview/reviews/templates/reviews/posts.html @@ -1,12 +1,46 @@ {% extends 'base.html' %} -{% block nav %} - -{% endblock %} + {% block content %} -

Posts

+
+
+
+

Posts

+
+
+ +
+ {% for ticket in tickets %} + {% include 'reviews/ticket_detail.html' %} + +
+ {% if perms.reviews.change_ticket %} +
+ Modifier +
+
+ Supprimer +
+
+ {% endif %} +
+ {% endfor %} + + + {% for review in reviews %} + {% include 'reviews/review_detail.html' %} +
+ {% if perms.reviews.change_ticket %} +
+ Modifier +
+
+ Supprimer +
+
+ {% endif %} +
+ {% endfor %} + + + {% endblock %} diff --git a/LITReview/reviews/templates/reviews/review.html b/LITReview/reviews/templates/reviews/review.html new file mode 100644 index 0000000..8c8a550 --- /dev/null +++ b/LITReview/reviews/templates/reviews/review.html @@ -0,0 +1,7 @@ +{% extends 'base.html' %} + +{% block content %} + +{% include 'reviews/review_detail.html' %} + +{% endblock %} \ No newline at end of file diff --git a/LITReview/reviews/templates/reviews/review_create.html b/LITReview/reviews/templates/reviews/review_create.html index 667e4cf..b9516aa 100644 --- a/LITReview/reviews/templates/reviews/review_create.html +++ b/LITReview/reviews/templates/reviews/review_create.html @@ -3,20 +3,28 @@ {% block content %}
-
+

Créer une critique

-
+

Livre/Article

-
- {% csrf_token %} - -
+
+ + {% include 'reviews/ticket_form.html' %} + {% csrf_token %} +
-
+

Critique

+
+ {% include 'reviews/review_form.html' %} +
+ +
+ +
diff --git a/LITReview/reviews/templates/reviews/review_delete.html b/LITReview/reviews/templates/reviews/review_delete.html new file mode 100644 index 0000000..8a7a52f --- /dev/null +++ b/LITReview/reviews/templates/reviews/review_delete.html @@ -0,0 +1,16 @@ +{% extends 'base.html' %} + +{% block content %} + +
+
+
+ {% csrf_token %} +

Êtes vous sûr de vouloir supprimer cette critique ?

+ +
+
+
+{% endblock %} + + diff --git a/LITReview/reviews/templates/reviews/review_detail.html b/LITReview/reviews/templates/reviews/review_detail.html new file mode 100644 index 0000000..1e0bdc8 --- /dev/null +++ b/LITReview/reviews/templates/reviews/review_detail.html @@ -0,0 +1,18 @@ +
+
+ {% if request.user == review.user %} + vous avez publié une critique + {% else %} + {{ review.user }} a publié une critique + {% endif %} +
+
+ {{ review.time_created }} +
+ + {{ review.headline }} - {{ review.rating }} ★ +

{{ review.comment }}

+
+ {% include 'reviews/ticket_detail.html' with ticket=review.ticket %} +
+
diff --git a/LITReview/reviews/templates/reviews/review_form.html b/LITReview/reviews/templates/reviews/review_form.html index db76c64..88d00c8 100644 --- a/LITReview/reviews/templates/reviews/review_form.html +++ b/LITReview/reviews/templates/reviews/review_form.html @@ -1,13 +1,11 @@ -
- {% csrf_token %} - -
{{ review_form.headline }}
- -
{{ review_form.rating }}
- -
{{ review_form.body }}
-
- -
-
+
+
{{ review_form.headline }}
+ +
+ {% for choice in review_form.rating %} + {{ choice }} + {% endfor %} +
+ +
{{ review_form.comment }}
diff --git a/LITReview/reviews/templates/reviews/review_form.html.2 b/LITReview/reviews/templates/reviews/review_form.html.2 new file mode 100644 index 0000000..980bcfc --- /dev/null +++ b/LITReview/reviews/templates/reviews/review_form.html.2 @@ -0,0 +1,10 @@ +
+ {% csrf_token %} + {{ review_form.headline }} + {% for radio in review_form.rating %} +
+ {{ radio }} +
+ {% endfor %} +
+ diff --git a/LITReview/reviews/templates/reviews/review_ticket.html b/LITReview/reviews/templates/reviews/review_ticket.html new file mode 100644 index 0000000..78e3cea --- /dev/null +++ b/LITReview/reviews/templates/reviews/review_ticket.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} + +{% block content %} + +
+
+
+

Créer une critique

+
+
+
+

Vous êtes en train de répondre à

+
+ {% include 'reviews/ticket_detail.html' %}
+
+
+ +
+

Critique

+
+
+ {% csrf_token %} + {% include 'reviews/review_form.html' %} + +
+ +
+ +
+
+
+ +{% endblock %} diff --git a/LITReview/reviews/templates/reviews/review_update.html b/LITReview/reviews/templates/reviews/review_update.html new file mode 100644 index 0000000..aa6674e --- /dev/null +++ b/LITReview/reviews/templates/reviews/review_update.html @@ -0,0 +1,42 @@ +{% extends 'base.html' %} + +{% block content %} + +
+
+
+

Modifier votre critique

+
+
+ +
+
+

Vous êtes en train de poster en réponse à

+
+
+ {% include 'reviews/ticket_detail.html' with ticket=review.ticket %} +
+
+
+
+
+

Critique

+
+ +
+
+ + {% csrf_token %} + {% include 'reviews/review_form.html' %} +
+ +
+ +
+
+
+
+ +{% endblock %} + + diff --git a/LITReview/reviews/templates/reviews/ticket_create.html b/LITReview/reviews/templates/reviews/ticket_create.html index 72d5945..dd2d25e 100644 --- a/LITReview/reviews/templates/reviews/ticket_create.html +++ b/LITReview/reviews/templates/reviews/ticket_create.html @@ -7,9 +7,17 @@

Créer un ticket

+
+
+
+ {% csrf_token %} + {{ ticket_form.as_p }} +
+ +
+
+
-
- {% include 'reviews/ticket_form.html' %}
diff --git a/LITReview/reviews/templates/reviews/ticket_detail.html b/LITReview/reviews/templates/reviews/ticket_detail.html index 85bd98f..42253bb 100644 --- a/LITReview/reviews/templates/reviews/ticket_detail.html +++ b/LITReview/reviews/templates/reviews/ticket_detail.html @@ -1,28 +1,17 @@
-
+
{% if request.user == ticket.user %} - vous avez demandé une critique + vous avez demandé une critique {% else %} - {{ ticket.user }} a demandé une critique + {{ ticket.user }} a demandé une critique {% endif %}
{{ ticket.time_created }}
-

{{ ticket.title }}

-

{{ ticket.body }}

+

{{ ticket.title }}

+

{{ ticket.desc }}

Couverture de {{ ticket.title }}
-
- {% if request.user == ticket.user %} -
- Modifier -
-
- Supprimer -
- {% endif %} -
-
diff --git a/LITReview/reviews/templates/reviews/ticket_detail.html.2 b/LITReview/reviews/templates/reviews/ticket_detail.html.2 new file mode 100644 index 0000000..85bd98f --- /dev/null +++ b/LITReview/reviews/templates/reviews/ticket_detail.html.2 @@ -0,0 +1,28 @@ +
+
+ {% if request.user == ticket.user %} + vous avez demandé une critique + {% else %} + {{ ticket.user }} a demandé une critique + {% endif %} +
+
+ {{ ticket.time_created }} +
+

{{ ticket.title }}

+

{{ ticket.body }}

+
+ Couverture de {{ ticket.title }} +
+
+ {% if request.user == ticket.user %} +
+ Modifier +
+
+ Supprimer +
+ {% endif %} +
+ +
diff --git a/LITReview/reviews/templates/reviews/ticket_form.html b/LITReview/reviews/templates/reviews/ticket_form.html index 838dee4..a2c1166 100644 --- a/LITReview/reviews/templates/reviews/ticket_form.html +++ b/LITReview/reviews/templates/reviews/ticket_form.html @@ -1,13 +1,6 @@ -
- {% csrf_token %} - -
{{ ticket_form.title }}
- -
{{ ticket_form.body }}
- -
{{ ticket_form.image }}
-
- -
-
- + +
{{ ticket_form.title }}
+ +
{{ ticket_form.desc }}
+ +
{{ ticket_form.image }}
diff --git a/LITReview/reviews/views.py b/LITReview/reviews/views.py index 87c9ea9..a254da3 100644 --- a/LITReview/reviews/views.py +++ b/LITReview/reviews/views.py @@ -1,7 +1,8 @@ from django.shortcuts import render, redirect -from django.contrib.auth.decorators import login_required -from reviews.models import Ticket -from reviews.forms import TicketForm +from django.contrib.auth.decorators import login_required, permission_required +from reviews.models import Ticket, Review +from reviews.forms import TicketForm, ReviewForm + @login_required def home(request): @@ -10,11 +11,21 @@ def home(request): @login_required def flux(request): - return render(request, 'reviews/flux.html') + tickets = Ticket.objects.all() + reviews = Review.objects.all() + context = { + 'tickets': tickets, + 'reviews': reviews, + } + return render(request, 'reviews/flux.html', context) @login_required def posts(request): - return render(request, 'reviews/posts.html') + tickets = Ticket.objects.filter(user=request.user) + reviews = Review.objects.filter(user=request.user) + return render(request, + 'reviews/posts.html', + {'tickets': tickets, 'reviews': reviews}) @login_required def subscribed(request): @@ -43,6 +54,7 @@ def create_ticket(request): context = {'ticket_form': ticket_form, 'tickets': tickets}) @login_required +@permission_required('review.change_ticket', raise_exception=True) def update_ticket(request, ticket_id): ticket = Ticket.objects.get(id=ticket_id) if request.method == 'POST': @@ -58,6 +70,7 @@ def update_ticket(request, ticket_id): {'ticket_form': ticket_form}) @login_required +@permission_required('review.onwer', raise_exception=True) def delete_ticket(request, ticket_id): ticket = Ticket.objects.get(id=ticket_id) if request.method == 'POST': @@ -68,17 +81,90 @@ def delete_ticket(request, ticket_id): 'reviews/ticket_delete.html', {'ticket': ticket}) -def review(request): - pass +@login_required +def review(request, review_id): + review = Review.objects.get(id=review_id) + ticket = review.ticket + return render(request, + 'reviews/review.html', + {'review': review}) +@login_required def create_review(request): - pass + ticket_form = TicketForm() + review_form = ReviewForm() + if request.method == 'POST': + ticket_form = TicketForm(request.POST, request.FILES) + review_form = ReviewForm(request.POST) + print(request.POST) -def update_review(request): - pass + if all([ticket_form.is_valid(), review_form.is_valid()]): + ticket = ticket_form.save(commit=False) + print(ticket) + ticket.user = request.user + ticket.save() + review = review_form.save(commit=False) + print(review) + review.user = request.user + review.ticket = ticket + review.save() + return redirect('posts') -def delete_review(request): - pass + context = { + 'ticket_form': ticket_form, + 'review_form': review_form, + } + return render(request, + 'reviews/review_create.html', context) + +@login_required +def ticket_review(request, ticket_id): + ticket = Ticket.objects.get(id=ticket_id) + review_form = ReviewForm() + if request.method == 'POST': + review_form = ReviewForm(request.POST) + print(request.POST) + if review_form.is_valid(): + review = review_form.save(commit=False) + review.user = request.user + review.ticket = ticket + review.save() + return redirect('posts') + context = { + 'ticket': ticket, + 'review_form': review_form, + } + return render(request, + 'reviews/review_ticket.html', context) + + +@login_required +def update_review(request, review_id): + review = Review.objects.get(id=review_id) + if request.method == 'POST': + print(request.POST) + review_form = ReviewForm(request.POST, instance=review) + print(review_form.is_valid()) + if review_form.is_valid(): + review = review_form.save() + return redirect('home') + else: + review_form = ReviewForm(instance=review) + + return render(request, + 'reviews/review_update.html', + {'review_form': review_form, 'review': review}) + +@login_required +@permission_required('review.owner', raise_exception=True) +def delete_review(request, review_id): + review = Review.objects.get(id=review_id) + if request.method == 'POST': + review.delete() + return redirect('posts') + return render(request, + 'reviews/review_delete.html', + {'review': review}) def follow_user(request): pass diff --git a/LITReview/templates/base.html b/LITReview/templates/base.html index 80668a3..ef26385 100644 --- a/LITReview/templates/base.html +++ b/LITReview/templates/base.html @@ -15,7 +15,9 @@

LITReview

+ {% if user.is_authenticated %} {% include 'nav.html' %} + {% endif %}
diff --git a/LITReview/templates/nav.html b/LITReview/templates/nav.html index c4379fe..4f73cc6 100644 --- a/LITReview/templates/nav.html +++ b/LITReview/templates/nav.html @@ -1,4 +1,3 @@ -{% if user.is_authenticated %} -{% endif %}