Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions core/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# Generated by Django 5.2.8 on 2025-12-04 12:34
# Generated by Django 5.2.8 on 2025-12-16 09:55

import django.contrib.auth.models
import django.contrib.auth.validators
import django.db.models.deletion
import django.utils.timezone
import pictures.models
import uuid
from django.conf import settings
from django.db import migrations, models

Expand All @@ -21,7 +22,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Badge',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('name', models.CharField(max_length=100, verbose_name='Nom')),
('icon_width', models.PositiveIntegerField(blank=True, editable=False, null=True)),
('icon_height', models.PositiveIntegerField(blank=True, editable=False, null=True)),
Expand All @@ -42,7 +43,6 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='User',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
Expand All @@ -53,6 +53,7 @@ class Migration(migrations.Migration):
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('uuid', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('avatar_width', models.PositiveIntegerField(blank=True, editable=False, null=True)),
('avatar_height', models.PositiveIntegerField(blank=True, editable=False, null=True)),
('avatar', pictures.models.PictureField(aspect_ratios=[None, '1/1', '3/2'], blank=True, breakpoints={'l': 1200, 'm': 992, 's': 768, 'xl': 1400, 'xs': 576}, container_width=1200, file_types=['WEBP'], grid_columns=12, height_field='avatar_height', null=True, pixel_densities=[1, 2], upload_to='users/avatars/', verbose_name='Avatar', width_field='avatar_width')),
Expand All @@ -61,8 +62,8 @@ class Migration(migrations.Migration):
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'Profil utilisateur',
'verbose_name_plural': 'Profils utilisateurs',
'verbose_name': 'Utilisateur',
'verbose_name_plural': 'Utilisateurs',
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
Expand All @@ -71,7 +72,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='BadgeHistory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('action', models.CharField(max_length=50, verbose_name='Action')),
('timestamp', models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date et heure')),
('details', models.TextField(blank=True, null=True, verbose_name='Détails')),
Expand All @@ -86,7 +87,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Structure',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('name', models.CharField(max_length=100, verbose_name='Nom')),
('logo_width', models.PositiveIntegerField(blank=True, editable=False, null=True)),
('logo_height', models.PositiveIntegerField(blank=True, editable=False, null=True)),
Expand Down Expand Up @@ -121,7 +122,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='BadgeAssignment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('assigned_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date d'attribution")),
('notes', models.TextField(blank=True, null=True, verbose_name='Notes')),
('assigned_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assigned_badges', to=settings.AUTH_USER_MODEL, verbose_name='Assigné par')),
Expand All @@ -138,7 +139,7 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='BadgeEndorsement',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.UUIDField(default=uuid.uuid7, primary_key=True, serialize=False)),
('endorsed_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date d'approbation")),
('notes', models.TextField(blank=True, null=True, verbose_name='Notes')),
('badge', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='endorsements', to='core.badge', verbose_name='Badge')),
Expand Down
19 changes: 19 additions & 0 deletions core/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import uuid
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
Expand All @@ -6,6 +7,9 @@
# Create your models here.

class User(AbstractUser):

uuid = models.UUIDField(default=uuid.uuid7, primary_key=True)

avatar_width = models.PositiveIntegerField(blank=True, null=True, editable=False)
avatar_height = models.PositiveIntegerField(blank=True, null=True, editable=False)
avatar = PictureField(upload_to='users/avatars/', blank=True, null=True, verbose_name="Avatar",
Expand Down Expand Up @@ -48,6 +52,9 @@ class Structure(models.Model):
"""
Model representing a structure (association, company, school, etc.)
"""

uuid = models.UUIDField(default=uuid.uuid7, primary_key=True)

TYPE_CHOICES = [
('association', 'Association'),
('company', 'Entreprise'),
Expand Down Expand Up @@ -95,6 +102,9 @@ class Badge(models.Model):
"""
Model representing a badge
"""

uuid = models.UUIDField(default=uuid.uuid7, primary_key=True)

LEVEL_CHOICES = [
('beginner', 'Débutant'),
('intermediate', 'Intermédiaire'),
Expand Down Expand Up @@ -168,6 +178,9 @@ class BadgeHistory(models.Model):
"""
Model to track the history of a badge (creation, modifications)
"""

uuid = models.UUIDField(default=uuid.uuid7, primary_key=True)

badge = models.ForeignKey(Badge, on_delete=models.CASCADE, related_name='history', verbose_name="Badge")
action = models.CharField(max_length=50, verbose_name="Action")
timestamp = models.DateTimeField(default=timezone.now, verbose_name="Date et heure")
Expand All @@ -186,6 +199,9 @@ class BadgeAssignment(models.Model):
"""
Model to track when a user receives a badge
"""

uuid = models.UUIDField(default=uuid.uuid7, primary_key=True)

badge = models.ForeignKey(Badge, on_delete=models.CASCADE, related_name='assignments', verbose_name="Badge")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='badge_assignments', verbose_name="Utilisateur")
assigned_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True,
Expand All @@ -208,6 +224,9 @@ class BadgeEndorsement(models.Model):
"""
Model to track when a structure endorses a badge
"""

uuid = models.UUIDField(default=uuid.uuid7, primary_key=True)

badge = models.ForeignKey(Badge, on_delete=models.CASCADE, related_name='endorsements', verbose_name="Badge")
structure = models.ForeignKey(Structure, on_delete=models.CASCADE, related_name='endorsed_badges',
verbose_name="Structure")
Expand Down
2 changes: 1 addition & 1 deletion core/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
path('user/create/',views.UserViewSet.as_view({'get': 'create_user', 'post': 'create_user'}),name='create_user'),

# Edition routes
path('users/<int:pk>/edit', views.UserViewSet.as_view({'get': 'edit', 'post': 'edit'}), name='edit-profile')
path('users/<str:pk>/edit', views.UserViewSet.as_view({'get': 'edit', 'post': 'edit'}), name='edit-profile')
]
4 changes: 2 additions & 2 deletions core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class HomeViewSet(viewsets.ViewSet):
"""
def list(self, request):
# Get some recent badges and structures for the home page
recent_badges = Badge.objects.all().order_by('-id')[:4]
popular_structures = Structure.objects.all().order_by('-id')[:4]
recent_badges = Badge.objects.all().order_by('-pk')[:4]
popular_structures = Structure.objects.all().order_by('-pk')[:4]

return render(request, 'core/home/index.html', {
'title': 'FossBadge - Accueil',
Expand Down
4 changes: 2 additions & 2 deletions templates/core/badges/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ <h5 class="card-title">Filtres</h5>
<select class="form-select" name="structure">
<option value="">Toutes les structures</option>
{% for structure in structures %}
<option value="{{ structure.id }}" {% if structure_filter == structure.id|stringformat:"i" %}selected{% endif %}>{{ structure.name }}</option>
<option value="{{ structure.pk }}" {% if structure_filter == structure.pk|stringformat:"i" %}selected{% endif %}>{{ structure.name }}</option>
{% endfor %}
</select>
</div>
Expand Down Expand Up @@ -93,7 +93,7 @@ <h5 class="card-title">{{ badge.name }}</h5>
{% endif %}
</p>
<p class="card-text text-muted">{{ badge.issuing_structure.name }}</p>
<a href="{% url 'core:badge-detail' pk=badge.id %}" class="btn btn-primary">Voir le badge</a>
<a href="{% url 'core:badge-detail' pk=badge.pk %}" class="btn btn-primary">Voir le badge</a>
</div>
</div>
{% endfor %}
Expand Down
2 changes: 1 addition & 1 deletion templates/core/badges/partials/badge_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ <h5 class="card-title">{{ badge.name }}</h5>
{% endif %}
</p>
<p class="card-text text-muted">{{ badge.issuing_structure.name }}</p>
<a href="{% url 'core:badge-detail' pk=badge.id %}" class="btn btn-primary">Voir le badge</a>
<a href="{% url 'core:badge-detail' pk=badge.pk %}" class="btn btn-primary">Voir le badge</a>
</div>
</div>
{% endfor %}
Expand Down
4 changes: 2 additions & 2 deletions templates/core/structures/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ <h1 class="display-4 mb-4">{{ structure.name }}</h1>
<img src="{{ placeholder_image }}" alt="Logo de {{ structure.name }}" class="img-fluid mb-3" style="max-width: 200px;">
{% endif %}
<h2 class="mb-3">{{ structure.name }}</h2>
<a href="{% url 'core:create_badge' %}?structure={{ structure.id }}" class="btn btn-primary mb-4">Forger un nouveau badge</a>
<a href="{% url 'core:create_badge' %}?structure={{ structure.pk }}" class="btn btn-primary mb-4">Forger un nouveau badge</a>
</div>

<div class="col-md-8">
Expand Down Expand Up @@ -130,7 +130,7 @@ <h5 class="card-title">{{ badge.name }}</h5>
<span class="badge bg-success">{{ badge.get_level_display }}</span>
{% endif %}
</p>
<a href="{% url 'core:badge-detail' pk=badge.id %}" class="btn btn-primary">Voir le badge</a>
<a href="{% url 'core:badge-detail' pk=badge.pk %}" class="btn btn-primary">Voir le badge</a>
</div>
</div>
{% endfor %}
Expand Down
4 changes: 2 additions & 2 deletions templates/core/structures/list.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ <h5 class="card-title">Filtres</h5>
<select class="form-select" name="badge">
<option value="">Tous les badges</option>
{% for badge in badges %}
<option value="{{ badge.id }}" {% if badge_filter == badge.id|stringformat:"i" %}selected{% endif %}>{{ badge.name }}</option>
<option value="{{ badge.pk }}" {% if badge_filter == badge.pk|stringformat:"i" %}selected{% endif %}>{{ badge.name }}</option>
{% endfor %}
</select>
</div>
Expand Down Expand Up @@ -89,7 +89,7 @@ <h5 class="card-title mb-0">{{ structure.name }}</h5>
<p class="card-text">{{ structure.description|truncatewords:30 }}</p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{ structure.issued_badges.count }} badge{% if structure.issued_badges.count != 1 %}s{% endif %} disponible{% if structure.issued_badges.count != 1 %}s{% endif %}</small>
<a href="{% url 'core:structure-detail' pk=structure.id %}" class="btn btn-primary">Voir la structure</a>
<a href="{% url 'core:structure-detail' pk=structure.pk %}" class="btn btn-primary">Voir la structure</a>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion templates/core/structures/partials/structure_list.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ <h5 class="card-title mb-0">{{ structure.name }}</h5>
<p class="card-text">{{ structure.description|truncatewords:30 }}</p>
<div class="d-flex justify-content-between align-items-center">
<small class="text-muted">{{ structure.issued_badges.count }} badge{% if structure.issued_badges.count != 1 %}s{% endif %} disponible{% if structure.issued_badges.count != 1 %}s{% endif %}</small>
<a href="{% url 'core:structure-detail' pk=structure.id %}" class="btn btn-primary">Voir la structure</a>
<a href="{% url 'core:structure-detail' pk=structure.pk %}" class="btn btn-primary">Voir la structure</a>
</div>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions templates/core/users/cv.html
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ <h3><i class="fa fa-briefcase"></i>Expérience</h3>
<ul>
{% if badges %}
{% for badge in badges|slice:":5" %}
{% with assignment=badge_assignment_dict|get_item:badge.id %}
{% with assignment=badge_assignment_dict|get_item:badge.pk %}
{% if assignment %}
<li>
<span>{{ badge.name }}</span>
Expand Down Expand Up @@ -549,7 +549,7 @@ <h3><i class="fas fa-building"></i>Structures visitées</h3>
<small>{{ structure_group.list|length }} badge{% if structure_group.list|length > 1 %}s{% endif %}</small>
<small>
{% with first_badge=structure_group.list.0 %}
{% with assignment=badge_assignment_dict|get_item:first_badge.id %}
{% with assignment=badge_assignment_dict|get_item:first_badge.pk %}
{% if assignment %}
Depuis {{ assignment.assigned_date|date:"M Y" }}
{% endif %}
Expand Down Expand Up @@ -614,7 +614,7 @@ <h3><i class="fas fa-code"></i>Compétences supplémentaires</h3>
<h3><i class="fa fa-briefcase"></i>Expérience supplémentaire</h3>
<ul>
{% for badge in badges|slice:"5:" %}
{% with assignment=badge_assignment_dict|get_item:badge.id %}
{% with assignment=badge_assignment_dict|get_item:badge.pk %}
{% if assignment %}
<li>
<span>{{ badge.name }}</span>
Expand All @@ -638,7 +638,7 @@ <h3><i class="fas fa-building"></i>Structures visitées supplémentaires</h3>
<small>{{ structure_group.list|length }} badge{% if structure_group.list|length > 1 %}s{% endif %}</small>
<small>
{% with first_badge=structure_group.list.0 %}
{% with assignment=badge_assignment_dict|get_item:first_badge.id %}
{% with assignment=badge_assignment_dict|get_item:first_badge.pk %}
{% if assignment %}
Depuis {{ assignment.assigned_date|date:"M Y" }}
{% endif %}
Expand Down
Loading