diff --git a/core/migrations/0005_activitylog.py b/core/migrations/0005_activitylog.py new file mode 100644 index 0000000..3fee87b --- /dev/null +++ b/core/migrations/0005_activitylog.py @@ -0,0 +1,21 @@ +# Generated by Django 4.0.8 on 2024-01-12 15:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0004_alter_newsandevents_id_alter_semester_id_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='ActivityLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('message', models.TextField()), + ('created_at', models.DateTimeField(auto_now=True)), + ], + ), + ] diff --git a/core/models.py b/core/models.py index a13ac44..b78f84e 100644 --- a/core/models.py +++ b/core/models.py @@ -84,3 +84,11 @@ class Semester(models.Model): def __str__(self): return self.semester + + +class ActivityLog(models.Model): + message = models.TextField() + created_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return f"[{self.created_at}]{self.message}" diff --git a/core/views.py b/core/views.py index ea40adf..e2da465 100644 --- a/core/views.py +++ b/core/views.py @@ -298,9 +298,11 @@ def semester_delete_view(request, pk): @login_required @admin_required def dashboard_view(request): + logs = ActivityLog.objects.all().order_by("-created_at")[:10] context = { "student_count": User.get_student_count(), "lecturer_count": User.get_lecturer_count(), "superuser_count": User.get_superuser_count(), + "logs": logs, } return render(request, "core/dashboard.html", context) diff --git a/course/models.py b/course/models.py index 1337169..d516dc9 100644 --- a/course/models.py +++ b/course/models.py @@ -2,11 +2,13 @@ from django.db import models from django.urls import reverse from django.conf import settings from django.core.validators import FileExtensionValidator -from django.db.models.signals import pre_save +from django.db.models.signals import pre_save, post_save, post_delete from django.db.models import Q +from django.dispatch import receiver # project import from .utils import * +from core.models import ActivityLog YEARS = ( (1, "1"), @@ -62,6 +64,17 @@ class Program(models.Model): return reverse("program_detail", kwargs={"pk": self.pk}) +@receiver(post_save, sender=Program) +def log_save(sender, instance, created, **kwargs): + verb = "created" if created else "updated" + ActivityLog.objects.create(message=f"The program '{instance}' has been {verb}.") + + +@receiver(post_delete, sender=Program) +def log_delete(sender, instance, **kwargs): + ActivityLog.objects.create(message=f"The program '{instance}' has been deleted.") + + class CourseManager(models.Manager): def search(self, query=None): queryset = self.get_queryset() @@ -118,6 +131,17 @@ def course_pre_save_receiver(sender, instance, *args, **kwargs): pre_save.connect(course_pre_save_receiver, sender=Course) +@receiver(post_save, sender=Course) +def log_save(sender, instance, created, **kwargs): + verb = "created" if created else "updated" + ActivityLog.objects.create(message=f"The course '{instance}' has been {verb}.") + + +@receiver(post_delete, sender=Course) +def log_delete(sender, instance, **kwargs): + ActivityLog.objects.create(message=f"The course '{instance}' has been deleted.") + + class CourseAllocation(models.Model): lecturer = models.ForeignKey( settings.AUTH_USER_MODEL, @@ -184,6 +208,25 @@ class Upload(models.Model): super().delete(*args, **kwargs) +@receiver(post_save, sender=Upload) +def log_save(sender, instance, created, **kwargs): + if created: + ActivityLog.objects.create( + message=f"The file '{instance.title}' has been uploaded to the course '{instance.course}'." + ) + else: + ActivityLog.objects.create( + message=f"The file '{instance.title}' of the course '{instance.course}' has been updated." + ) + + +@receiver(post_delete, sender=Upload) +def log_delete(sender, instance, **kwargs): + ActivityLog.objects.create( + message=f"The file '{instance.title}' of the course '{instance.course}' has been deleted." + ) + + class UploadVideo(models.Model): title = models.CharField(max_length=100) slug = models.SlugField(blank=True, unique=True) @@ -218,6 +261,25 @@ def video_pre_save_receiver(sender, instance, *args, **kwargs): pre_save.connect(video_pre_save_receiver, sender=UploadVideo) +@receiver(post_save, sender=UploadVideo) +def log_save(sender, instance, created, **kwargs): + if created: + ActivityLog.objects.create( + message=f"The video '{instance.title}' has been uploaded to the course {instance.course}." + ) + else: + ActivityLog.objects.create( + message=f"The video '{instance.title}' of the course '{instance.course}' has been updated." + ) + + +@receiver(post_delete, sender=UploadVideo) +def log_delete(sender, instance, **kwargs): + ActivityLog.objects.create( + message=f"The video '{instance.title}' of the course '{instance.course}' has been deleted." + ) + + class CourseOffer(models.Model): """NOTE: Only department head can offer semester courses""" diff --git a/templates/core/dashboard.html b/templates/core/dashboard.html index da06ecb..bde9eef 100644 --- a/templates/core/dashboard.html +++ b/templates/core/dashboard.html @@ -275,16 +275,13 @@