diff --git a/backend/core/settings.py b/backend/core/settings.py index 3d565d0..79e243d 100644 --- a/backend/core/settings.py +++ b/backend/core/settings.py @@ -49,6 +49,7 @@ INSTALLED_APPS = [ 'time_tracking', 'events', 'notes', + 'file', # Ajout du module de gestion des fichiers ] MIDDLEWARE = [ @@ -156,3 +157,4 @@ SIMPLE_JWT = { # Default primary key field type # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + diff --git a/backend/core/urls.py b/backend/core/urls.py index d3c95e9..e7dc65f 100644 --- a/backend/core/urls.py +++ b/backend/core/urls.py @@ -29,4 +29,5 @@ urlpatterns = [ path('api/time/', include('time_tracking.urls')), path('api/event/', include('events.urls')), path('api/notes/', include('notes.urls')), + path('api/file/', include('file.urls')), # Ajout des URLs du module file ] diff --git a/backend/file/apps.py b/backend/file/apps.py new file mode 100644 index 0000000..c2f9023 --- /dev/null +++ b/backend/file/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class FileConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'file' \ No newline at end of file diff --git a/backend/file/migrations/0001_initial.py b/backend/file/migrations/0001_initial.py new file mode 100644 index 0000000..0c8787f --- /dev/null +++ b/backend/file/migrations/0001_initial.py @@ -0,0 +1,30 @@ +# Generated by Django 5.2.17 on 2026-09-25 17:20 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='File', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('path', models.CharField(max_length=500)), + ('content', models.FileField(upload_to='files/')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('type', models.CharField(choices=[('pay_slip', 'Fiche de paie'), ('timetable', 'Emploi du temps'), ('contract', 'Contrat'), ('identity', "Pièce d'identité"), ('other', 'Autre')], max_length=50)), + ('display_path', models.CharField(blank=True, max_length=500)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='files', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/backend/file/migrations/__init__.py b/backend/file/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/file/models.py b/backend/file/models.py new file mode 100644 index 0000000..65251ff --- /dev/null +++ b/backend/file/models.py @@ -0,0 +1,23 @@ +from django.db import models +from django.contrib.auth import get_user_model + +User = get_user_model() + +class FileType(models.TextChoices): + PAY_SLIP = 'pay_slip', 'Fiche de paie' + TIMETABLE = 'timetable', 'Emploi du temps' + CONTRACT = 'contract', 'Contrat' + IDENTITY = 'identity', 'Pièce d\'identité' + OTHER = 'other', 'Autre' + +class File(models.Model): + name = models.CharField(max_length=255) + path = models.CharField(max_length=500) + content = models.FileField(upload_to='files/') + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='files') + created_at = models.DateTimeField(auto_now_add=True) + type = models.CharField(max_length=50, choices=FileType.choices) + display_path = models.CharField(max_length=500, blank=True) + + def __str__(self): + return f"{self.name} - {self.user.username}" \ No newline at end of file diff --git a/backend/file/serializers.py b/backend/file/serializers.py new file mode 100644 index 0000000..3b1cd3a --- /dev/null +++ b/backend/file/serializers.py @@ -0,0 +1,8 @@ +from rest_framework import serializers +from .models import File, FileType + +class FileSerializer(serializers.ModelSerializer): + class Meta: + model = File + fields = ['id', 'name', 'path', 'content', 'user', 'created_at', 'type', 'display_path'] + read_only_fields = ['user', 'created_at'] \ No newline at end of file diff --git a/backend/file/urls.py b/backend/file/urls.py new file mode 100644 index 0000000..4a6639c --- /dev/null +++ b/backend/file/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from .views import FileListView, FileUploadView, FileDetailView + +urlpatterns = [ + path('files/', FileListView.as_view(), name='file-list'), + path('files/upload/', FileUploadView.as_view(), name='file-upload'), + path('files//', FileDetailView.as_view(), name='file-detail'), +] \ No newline at end of file diff --git a/backend/file/views.py b/backend/file/views.py new file mode 100644 index 0000000..d56c3b7 --- /dev/null +++ b/backend/file/views.py @@ -0,0 +1,27 @@ +from rest_framework import generics, status +from rest_framework.response import Response +from rest_framework.permissions import IsAuthenticated +from .models import File +from .serializers import FileSerializer + +class FileListView(generics.ListAPIView): + serializer_class = FileSerializer + permission_classes = [IsAuthenticated] + + def get_queryset(self): + return File.objects.filter(user=self.request.user) + +class FileUploadView(generics.CreateAPIView): + serializer_class = FileSerializer + permission_classes = [IsAuthenticated] + + def perform_create(self, serializer): + serializer.save(user=self.request.user) + +class FileDetailView(generics.RetrieveUpdateDestroyAPIView): + serializer_class = FileSerializer + permission_classes = [IsAuthenticated] + lookup_field = 'id' + + def get_queryset(self): + return File.objects.filter(user=self.request.user) \ No newline at end of file diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e1dcd7c..c3f0c12 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -24,6 +24,7 @@ import TimeClockPage from './pages/TimeClockPage'; import WeeklySummaryPage from './pages/WeeklySummaryPage'; import CalendarPage from './pages/CalendarPage'; import NotesPage from './pages/NotesPage'; +import ManageUsersPage from './pages/ManageUsersPage'; import { useAuth } from './context/useAuth'; // Composant personnalisé pour le trigger mobile avec icône menu @@ -120,6 +121,15 @@ function App() { } /> + + + + } + /> + } /> - -