mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-21 11:51:10 -05:00
Add history tracking functionality using django-pghistory; implement views, templates, and middleware for event serialization and context management
This commit is contained in:
12
history/apps.py
Normal file
12
history/apps.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
class HistoryConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'history'
|
||||
verbose_name = 'History Tracking'
|
||||
|
||||
def ready(self):
|
||||
"""Initialize app and signal handlers"""
|
||||
from django.dispatch import Signal
|
||||
# Create a signal for history updates
|
||||
self.history_updated = Signal()
|
||||
29
history/templates/history/partials/history_timeline.html
Normal file
29
history/templates/history/partials/history_timeline.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<div id="history-timeline"
|
||||
hx-get="{% url 'history:timeline' content_type_id=content_type.id object_id=object.id %}"
|
||||
hx-trigger="every 30s, historyUpdate from:body">
|
||||
<div class="space-y-4">
|
||||
{% for event in events %}
|
||||
<div class="component-wrapper bg-white p-4 shadow-sm">
|
||||
<div class="component-header flex items-center gap-2 mb-2">
|
||||
<span class="text-sm font-medium">{{ event.pgh_label|title }}</span>
|
||||
<time class="text-xs text-gray-500">{{ event.pgh_created_at|date:"M j, Y H:i" }}</time>
|
||||
</div>
|
||||
<div class="component-content text-sm">
|
||||
{% if event.pgh_context.metadata.user %}
|
||||
<div class="flex items-center gap-1">
|
||||
<svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fill-rule="evenodd" d="M10 9a3 3 0 100-6 3 3 0 000 6zm-7 9a7 7 0 1114 0H3z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
<span>{{ event.pgh_context.metadata.user }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if event.pgh_data %}
|
||||
<div class="mt-2 text-gray-600">
|
||||
<pre class="text-xs">{{ event.pgh_data|pprint }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
17
history/templatetags/history_tags.py
Normal file
17
history/templatetags/history_tags.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from django import template
|
||||
import json
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.filter
|
||||
def pprint(value):
|
||||
"""Pretty print JSON data"""
|
||||
if isinstance(value, str):
|
||||
try:
|
||||
value = json.loads(value)
|
||||
except json.JSONDecodeError:
|
||||
return value
|
||||
|
||||
if isinstance(value, (dict, list)):
|
||||
return json.dumps(value, indent=2)
|
||||
return str(value)
|
||||
10
history/urls.py
Normal file
10
history/urls.py
Normal file
@@ -0,0 +1,10 @@
|
||||
from django.urls import path
|
||||
from .views import HistoryTimelineView
|
||||
|
||||
app_name = 'history'
|
||||
|
||||
urlpatterns = [
|
||||
path('timeline/<int:content_type_id>/<int:object_id>/',
|
||||
HistoryTimelineView.as_view(),
|
||||
name='timeline'),
|
||||
]
|
||||
41
history/views.py
Normal file
41
history/views.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from django.views import View
|
||||
from django.shortcuts import render
|
||||
from django.http import JsonResponse
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
import pghistory
|
||||
|
||||
def serialize_event(event):
|
||||
"""Serialize a history event for JSON response"""
|
||||
return {
|
||||
'label': event.pgh_label,
|
||||
'created_at': event.pgh_created_at.isoformat(),
|
||||
'context': event.pgh_context,
|
||||
'data': event.pgh_data,
|
||||
}
|
||||
|
||||
class HistoryTimelineView(View):
|
||||
"""View for displaying object history timeline"""
|
||||
|
||||
def get(self, request, content_type_id, object_id):
|
||||
# Get content type and object
|
||||
content_type = ContentType.objects.get_for_id(content_type_id)
|
||||
obj = content_type.get_object_for_this_type(id=object_id)
|
||||
|
||||
# Get history events
|
||||
events = pghistory.models.Event.objects.filter(
|
||||
pgh_obj_model=content_type.model_class(),
|
||||
pgh_obj_id=object_id
|
||||
).order_by('-pgh_created_at')[:25]
|
||||
|
||||
context = {
|
||||
'events': events,
|
||||
'content_type': content_type,
|
||||
'object': obj,
|
||||
}
|
||||
|
||||
if request.htmx:
|
||||
return render(request, "history/partials/history_timeline.html", context)
|
||||
|
||||
return JsonResponse({
|
||||
'history': [serialize_event(e) for e in events]
|
||||
})
|
||||
Reference in New Issue
Block a user