diff --git a/peachjam/admin.py b/peachjam/admin.py index 5e91b4cd9..8f7c68968 100644 --- a/peachjam/admin.py +++ b/peachjam/admin.py @@ -86,6 +86,7 @@ citations_processor, pj_settings, ) +from peachjam.models.activity import EditActivity from peachjam.plugins import plugins from peachjam.resources import ( ArticleResource, @@ -286,6 +287,8 @@ def value_from_datadict(self, data, files, name): class DocumentForm(forms.ModelForm): + # to track edit activity + edit_activity_start = forms.DateTimeField(widget=forms.HiddenInput(), required=True) content_html = forms.CharField( widget=CKEditorWidget( extra_plugins=["lawwidgets"], @@ -338,6 +341,8 @@ def __init__(self, data=None, *args, **kwargs): if self.instance and self.instance.content_html_is_akn: self.fields["content_html"].widget.attrs["readonly"] = True + self.fields["edit_activity_start"].initial = timezone.now() + def clean_content_html(self): # prevent CKEditor-based editing of AKN HTML if self.instance.content_html_is_akn: @@ -527,6 +532,15 @@ def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) + # update the edit activity end time + EditActivity.objects.create( + document=obj, + user=request.user, + stage="corrections" if change else "initial", + start=form.cleaned_data["edit_activity_start"], + end=timezone.now(), + ) + def save_related(self, request, form, formsets, change): # after saving related models, also save this model again so that it can update fields based on related changes # if date, title, or content changed, re-extract citations or if new document diff --git a/peachjam/migrations/0165_editactivity.py b/peachjam/migrations/0165_editactivity.py new file mode 100644 index 000000000..e4c98cf4b --- /dev/null +++ b/peachjam/migrations/0165_editactivity.py @@ -0,0 +1,61 @@ +# Generated by Django 4.2.14 on 2024-10-10 13:20 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("peachjam", "0164_peachjamsettings_robots_txt"), + ] + + operations = [ + migrations.CreateModel( + name="EditActivity", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("start", models.DateTimeField()), + ("end", models.DateTimeField()), + ("seconds", models.IntegerField()), + ( + "stage", + models.CharField( + choices=[ + ("initial", "initial"), + ("corrections", "corrections"), + ], + default="initial", + max_length=255, + ), + ), + ( + "document", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="peachjam.coredocument", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), + ], + options={ + "ordering": ("start",), + }, + ), + ] diff --git a/peachjam/models/activity.py b/peachjam/models/activity.py new file mode 100644 index 000000000..6a7006194 --- /dev/null +++ b/peachjam/models/activity.py @@ -0,0 +1,26 @@ +from django.contrib.auth.models import User +from django.db import models + +from peachjam.models import CoreDocument + + +class EditActivity(models.Model): + """Time spent editing a document via the admin area.""" + + document = models.ForeignKey(CoreDocument, on_delete=models.CASCADE) + user = models.ForeignKey(User, on_delete=models.CASCADE) + start = models.DateTimeField() + end = models.DateTimeField() + seconds = models.IntegerField() + stage = models.CharField( + max_length=255, + choices=(("initial", "initial"), ("corrections", "corrections")), + default="initial", + ) + + class Meta: + ordering = ("start",) + + def save(self, *args, **kwargs): + self.seconds = (self.end - self.start).total_seconds() + super().save(*args, **kwargs) diff --git a/peachjam/templates/admin/change_form.html b/peachjam/templates/admin/change_form.html index 6a9b3a053..84b743b1e 100644 --- a/peachjam/templates/admin/change_form.html +++ b/peachjam/templates/admin/change_form.html @@ -1,5 +1,9 @@ {% extends "admin/change_form.html" %} {% load i18n comments humanize static %} +{% block form_top %} + {{ block.super }} + {% if adminform.form.edit_activity_start %}{{ adminform.form.edit_activity_start.as_hidden }}{% endif %} +{% endblock %} {% block extra_actions %} {{ block.super }} {% if PEACHJAM_SETTINGS.editor_help_link and adminform.model_admin.help_topic %}