added the pagination for auditlog dashboard
This commit is contained in:
parent
679188dad8
commit
bf17338a29
@ -31,7 +31,7 @@ from django.forms import HiddenInput, ValidationError
|
||||
from django.shortcuts import HttpResponse
|
||||
|
||||
from django.db.models import Sum, F, Count
|
||||
from django.core.paginator import Paginator
|
||||
from django.core.paginator import Paginator,EmptyPage, PageNotAnInteger
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db.models import Value
|
||||
@ -8273,106 +8273,26 @@ def user_management(request):
|
||||
}
|
||||
return render(request, "admin_management/user_management.html", context)
|
||||
|
||||
#audit log Management
|
||||
|
||||
# class AuditLogDashboardView(TemplateView):
|
||||
# """
|
||||
# Displays a dashboard with tabs for different audit log types.
|
||||
# Fetches all necessary log data to pass to the template.
|
||||
# """
|
||||
# template_name = 'admin_management/audit_log_dashboard.html' # Name of your main template with tabs
|
||||
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
|
||||
# # Fetch data for each log type
|
||||
# # Order by 'datetime' field as per easy_audit models
|
||||
# context['model_events'] = CRUDEvent.objects.all().order_by('-datetime')
|
||||
# context['auth_events'] = LoginEvent.objects.all().order_by('-datetime')
|
||||
# context['request_events'] = RequestEvent.objects.all().order_by('-datetime')
|
||||
# return context
|
||||
|
||||
def AuditLogDashboardView(request):
|
||||
query=request.GET.get('q')
|
||||
context={}
|
||||
model_events_raw = CRUDEvent.objects.all().order_by('-datetime')
|
||||
processed_model_events = []
|
||||
|
||||
for event in model_events_raw:
|
||||
# Create a base dictionary for each event's data
|
||||
event_data = {
|
||||
'datetime': event.datetime,
|
||||
'user': event.user,
|
||||
'event_type_display': event.get_event_type_display(),
|
||||
'model_name': event.content_type.model,
|
||||
'object_id': event.object_id,
|
||||
'object_repr': event.object_repr,
|
||||
'field_changes': [] # This will be a list of dicts: [{'field': 'name', 'old': 'A', 'new': 'B'}]
|
||||
}
|
||||
|
||||
if event.changed_fields:
|
||||
try:
|
||||
print(f"Debugging CRUDEvent ID: {event.id}, User: {event.user}, Model: {event.content_type.model}")
|
||||
print(f"Raw event.changed_fields: '{event.changed_fields}' (Type: {type(event.changed_fields)})")
|
||||
changes = json.loads(event.changed_fields)
|
||||
#change_fields returns 'null' for no changes to a field i.e. if the field remains the same
|
||||
if isinstance(changes, dict): # Check if 'changes' is a dictionary
|
||||
for field_name, values in changes.items():
|
||||
old_value = values[0] if isinstance(values, list) and len(values) > 0 else None
|
||||
new_value = values[1] if isinstance(values, list) and len(values) > 1 else None
|
||||
event_data['field_changes'].append({
|
||||
'field': field_name,
|
||||
'old': old_value,
|
||||
'new': new_value
|
||||
})
|
||||
elif changes is None: # Handle case where JSON was 'null' string like when no changes detected for a field or if it saved without a change
|
||||
|
||||
event_data['field_changes'].append({
|
||||
'field': 'Info',
|
||||
'old': '',
|
||||
'new': 'No specific field changes recorded (JSON was null)'
|
||||
})
|
||||
else: # Handle valid JSON but not a dictionary (e.g., "[]", 123)
|
||||
event_data['field_changes'].append({
|
||||
'field': 'Error',
|
||||
'old': '',
|
||||
'new': f'Unexpected JSON format: {type(changes).__name__}'
|
||||
})
|
||||
except json.JSONDecodeError:
|
||||
# Handle invalid JSON; you might log this error
|
||||
event_data['field_changes'].append({
|
||||
'field': 'Error',
|
||||
'old': '',
|
||||
'new': 'Invalid JSON in changed_fields'
|
||||
})
|
||||
|
||||
processed_model_events.append(event_data)
|
||||
|
||||
context['model_events'] = processed_model_events
|
||||
context['auth_events'] = LoginEvent.objects.all().order_by('-datetime')
|
||||
context['request_events'] = RequestEvent.objects.all().order_by('-datetime')
|
||||
if(query=='userActions'):
|
||||
return render(request,'admin_management/model_logs.html',context)
|
||||
elif(query=='loginEvents'):
|
||||
return render(request,'admin_management/auth_logs.html',context)
|
||||
else:
|
||||
return render(request,'admin_management/request_logs.html',context)
|
||||
|
||||
|
||||
|
||||
|
||||
# class AuditLogDashboardView(TemplateView):
|
||||
# template_name = 'admin_management/audit_log_dashboard.html'
|
||||
# paginate_by = 20
|
||||
|
||||
# def get_context_data(self, **kwargs):
|
||||
# context = super().get_context_data(**kwargs)
|
||||
|
||||
# # Process CRUD (Model Change) Events
|
||||
# def AuditLogDashboardView(request):
|
||||
# q=request.GET.get('q')
|
||||
|
||||
# context={}
|
||||
# model_events_raw = CRUDEvent.objects.all().order_by('-datetime')
|
||||
# processed_model_events = []
|
||||
# page = request.GET.get('page', 1)
|
||||
|
||||
# for event in model_events_raw:
|
||||
|
||||
|
||||
# # context['model_events'] = processed_model_events
|
||||
# # context['auth_events'] = LoginEvent.objects.all().order_by('-datetime')
|
||||
# # context['request_events'] = RequestEvent.objects.all().order_by('-datetime')
|
||||
# if(q=='userActions'):
|
||||
# for event in model_events_raw:
|
||||
# # Create a base dictionary for each event's data
|
||||
# event_data = {
|
||||
# 'datetime': event.datetime,
|
||||
@ -8386,8 +8306,8 @@ def AuditLogDashboardView(request):
|
||||
|
||||
# if event.changed_fields:
|
||||
# try:
|
||||
# print(f"Debugging CRUDEvent ID: {event.id}, User: {event.user}, Model: {event.content_type.model}")
|
||||
# print(f"Raw event.changed_fields: '{event.changed_fields}' (Type: {type(event.changed_fields)})")
|
||||
# # print(f"Debugging CRUDEvent ID: {event.id}, User: {event.user}, Model: {event.content_type.model}")
|
||||
# # print(f"Raw event.changed_fields: '{event.changed_fields}' (Type: {type(event.changed_fields)})")
|
||||
# changes = json.loads(event.changed_fields)
|
||||
# #change_fields returns 'null' for no changes to a field i.e. if the field remains the same
|
||||
# if isinstance(changes, dict): # Check if 'changes' is a dictionary
|
||||
@ -8418,19 +8338,152 @@ def AuditLogDashboardView(request):
|
||||
# 'field': 'Error',
|
||||
# 'old': '',
|
||||
# 'new': 'Invalid JSON in changed_fields'
|
||||
# })
|
||||
# })
|
||||
|
||||
# processed_model_events.append(event_data)
|
||||
|
||||
# context['model_events'] = processed_model_events
|
||||
# context['auth_events'] = LoginEvent.objects.all().order_by('-datetime')
|
||||
# context['request_events'] = RequestEvent.objects.all().order_by('-datetime')
|
||||
|
||||
# return context
|
||||
# paginator=Paginator(processed_model_events,10)
|
||||
# page_obj=paginator.page(page)
|
||||
# context={
|
||||
# 'page_obj':page_obj
|
||||
# }
|
||||
# return render(request,'admin_management/model_logs.html',context)
|
||||
|
||||
# elif(q=='loginEvents'):
|
||||
# auth_events = LoginEvent.objects.all().order_by('-datetime')
|
||||
# paginator=Paginator(auth_events,10)
|
||||
# page_obj=paginator.page(page)
|
||||
# context={
|
||||
# 'page_obj':page_obj
|
||||
# }
|
||||
# return render(request,'admin_management/auth_logs.html',context)
|
||||
# else:
|
||||
# request_events= RequestEvent.objects.all().order_by('-datetime')
|
||||
# paginator=Paginator(request_events,10)
|
||||
# page_obj=paginator.page(page)
|
||||
# context={
|
||||
# 'page_obj':page_obj
|
||||
# }
|
||||
# return render(request,'admin_management/request_logs.html',context)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def AuditLogDashboardView(request):
|
||||
"""
|
||||
Displays audit logs (User Actions, Login Events, Request Events) with pagination.
|
||||
Log type is determined by the 'q' query parameter (e.g., ?q=userActions).
|
||||
Pagination page number is passed as a query parameter (e.g., ?page=2).
|
||||
"""
|
||||
q = request.GET.get('q') # Get the log type from the 'q' query parameter
|
||||
current_pagination_page = request.GET.get('page', 1)
|
||||
context = {}
|
||||
template_name = None
|
||||
logs_per_page = 30 # Define logs per page once
|
||||
|
||||
# --- Determine Data Source and Template based on 'q' parameter ---
|
||||
if q=='userRequests': # This block handles cases where 'q' is 'requestEvents', None, or any other invalid value.
|
||||
# It defaults to Request Logs if 'q' is not 'userActions' or 'loginEvents'.
|
||||
template_name = 'admin_management/request_logs.html'
|
||||
context['title'] = 'Request Logs Dashboard'
|
||||
request_events = RequestEvent.objects.all().order_by('-datetime')
|
||||
paginator = Paginator(request_events, logs_per_page)
|
||||
try:
|
||||
page_obj = paginator.page(current_pagination_page)
|
||||
except PageNotAnInteger:
|
||||
page_obj = paginator.page(1)
|
||||
except EmptyPage:
|
||||
page_obj = paginator.page(paginator.num_pages)
|
||||
|
||||
|
||||
elif q == 'loginEvents':
|
||||
template_name = 'admin_management/auth_logs.html'
|
||||
context['title'] = 'Login Events Dashboard'
|
||||
auth_events = LoginEvent.objects.all().order_by('-datetime')
|
||||
paginator = Paginator(auth_events, logs_per_page)
|
||||
try:
|
||||
page_obj = paginator.page(current_pagination_page)
|
||||
except PageNotAnInteger:
|
||||
page_obj = paginator.page(1)
|
||||
except EmptyPage:
|
||||
page_obj = paginator.page(paginator.num_pages)
|
||||
|
||||
else:
|
||||
template_name = 'admin_management/model_logs.html'
|
||||
context['title'] = 'User Actions Dashboard'
|
||||
|
||||
# OPTIMIZATION: Get the QuerySet but don't evaluate it yet
|
||||
model_events_queryset = CRUDEvent.objects.all().order_by('-datetime')
|
||||
|
||||
# 1. Paginate the raw QuerySet FIRST
|
||||
paginator = Paginator(model_events_queryset, logs_per_page)
|
||||
|
||||
try:
|
||||
# Get the page object, which contains only the raw QuerySet objects for the current page
|
||||
page_obj_raw = paginator.page(current_pagination_page)
|
||||
except PageNotAnInteger:
|
||||
page_obj_raw = paginator.page(1)
|
||||
except EmptyPage:
|
||||
page_obj_raw = paginator.page(paginator.num_pages)
|
||||
|
||||
# 2. Now, process 'field_changes' ONLY for the events on the current page
|
||||
processed_model_events_for_page = []
|
||||
for event in page_obj_raw.object_list: # Loop only through the current page's items
|
||||
event_data = {
|
||||
'datetime': event.datetime,
|
||||
'user': event.user,
|
||||
'event_type_display': event.get_event_type_display(),
|
||||
'model_name': event.content_type.model,
|
||||
'object_id': event.object_id,
|
||||
'object_repr': event.object_repr,
|
||||
'field_changes': []
|
||||
}
|
||||
|
||||
if event.changed_fields:
|
||||
try:
|
||||
changes = json.loads(event.changed_fields)
|
||||
if isinstance(changes, dict):
|
||||
for field_name, values in changes.items():
|
||||
old_value = values[0] if isinstance(values, list) and len(values) > 0 else None
|
||||
new_value = values[1] if isinstance(values, list) and len(values) > 1 else None
|
||||
event_data['field_changes'].append({
|
||||
'field': field_name,
|
||||
'old': old_value,
|
||||
'new': new_value
|
||||
})
|
||||
elif changes is None:
|
||||
event_data['field_changes'].append({
|
||||
'field': 'Info',
|
||||
'old': '',
|
||||
'new': 'No specific field changes recorded (JSON was null)'
|
||||
})
|
||||
else: # Handle valid JSON but not a dictionary (e.g., "[]", 123)
|
||||
event_data['field_changes'].append({
|
||||
'field': 'Error',
|
||||
'old': '',
|
||||
'new': f'Unexpected JSON format: {type(changes).__name__}'
|
||||
})
|
||||
except json.JSONDecodeError:
|
||||
# Handle invalid JSON; you might log this error
|
||||
event_data['field_changes'].append({
|
||||
'field': 'Error',
|
||||
'old': '',
|
||||
'new': 'Invalid JSON in changed_fields'
|
||||
})
|
||||
processed_model_events_for_page.append(event_data)
|
||||
|
||||
# 3. Replace the object_list of the original page_obj with the processed data
|
||||
# This keeps all pagination properties (has_next, number, etc.) intact.
|
||||
page_obj_raw.object_list = processed_model_events_for_page
|
||||
page_obj = page_obj_raw # This will be passed to the context
|
||||
|
||||
# Pass the final page object to the context
|
||||
context['page_obj'] = page_obj
|
||||
|
||||
return render(request, template_name, context)
|
||||
|
||||
|
||||
|
||||
|
||||
def activate_account(request, content_type, slug):
|
||||
try:
|
||||
|
||||
@ -1,68 +0,0 @@
|
||||
{% extends "base.html" %}
|
||||
{% load i18n custom_filters %}
|
||||
{% block title %}{% trans "Accounts" %}{% endblock title %}
|
||||
{% block accounts %}
|
||||
<a class="nav-link active fw-bold">
|
||||
{% trans "Accounts"|capfirst %}
|
||||
<span class="visually-hidden">(current)</span>
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="row mt-4">
|
||||
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<h3 class=""><i class="fa-solid fa-book"></i> {% trans "Audit Log Dashboard" %}</h3>
|
||||
</div>
|
||||
|
||||
<!-- Log Type Tabs -->
|
||||
<div class="mb-4">
|
||||
<ul class="nav nav-tabs" id="accountTypeTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="modellogs-tab" data-bs-toggle="tab" data-bs-target="#modellogs" type="button" role="tab" aria-controls="modellogs" aria-selected="true">
|
||||
<i class="fas fa-wallet me-2"></i>{% trans "User Actions" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="authlogs-tab" data-bs-toggle="tab" data-bs-target="#authlogs" type="button" role="tab" aria-controls="authlogs" aria-selected="false">
|
||||
<i class="fas fa-boxes me-2"></i>{% trans "User Login Events" %}
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="requestslog-tab" data-bs-toggle="tab" data-bs-target="#requestslog" type="button" role="tab" aria-controls="requestslog" aria-selected="false">
|
||||
<i class="fas fa-landmark me-2"></i>{% trans "User Page Requests" %}
|
||||
</button>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent">
|
||||
<!-- modellogs Tab -->
|
||||
<div class="tab-pane fade show active" id="modellogs" role="tabpanel" aria-labelledby="modellogs-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% include "admin_management/model_logs.html" %}
|
||||
|
||||
</div>
|
||||
|
||||
<!-- authlogs Tab -->
|
||||
<div class="tab-pane fade" id="authlogs" role="tabpanel" aria-labelledby="authlogs-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% include "admin_management/auth_logs.html" %}
|
||||
|
||||
</div>
|
||||
|
||||
<!-- requestslog Tab -->
|
||||
<div class="tab-pane fade" id="requestslog" role="tabpanel" aria-labelledby="requestslog-tab">
|
||||
{% include "partials/search_box.html" %}
|
||||
{% include "admin_management/request_logs.html" %}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent">
|
||||
<!-- modellogs Tab -->
|
||||
|
||||
{% if auth_events %}
|
||||
{% if page_obj %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class= "table align-items-center table-flush table-hover">
|
||||
<thead>
|
||||
@ -35,7 +35,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list">
|
||||
{% for event in auth_events %}
|
||||
{% for event in page_obj.object_list %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
|
||||
<td class="align-middle product white-space-nowrap">{{event.datetime}}</td>
|
||||
@ -49,7 +49,15 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end mt-3">
|
||||
<div class="d-flex">
|
||||
{% if is_paginated %}
|
||||
{% include 'partials/pagination.html' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% include 'partials/pagination_audit.html' with q='loginEvents' %}
|
||||
|
||||
{% else %}
|
||||
<p>No authentication audit events found.</p>
|
||||
{% endif %}
|
||||
|
||||
@ -22,69 +22,69 @@
|
||||
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent">
|
||||
<!-- modellogs Tab -->
|
||||
|
||||
{% if model_events %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush table-hover mt-3">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<th>{% trans "Timestamp" %}</th>
|
||||
<th>{% trans "User" %}</th>
|
||||
<th>{% trans "Action" %}</th>
|
||||
<th>{% trans "Model" %}</th>
|
||||
<th>{% trans "Object ID" %}</th>
|
||||
<th>{% trans "Object Representation" %}</th>
|
||||
<th>{% trans "Field" %}</th> {# Dedicated column for field name #}
|
||||
<th>{% trans "Old Value" %}</th> {# Dedicated column for old value #}
|
||||
<th>{% trans "New Value" %}</th> {# Dedicated column for new value #}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for event in model_events %}
|
||||
{% if event.field_changes %}
|
||||
{% if page_obj %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class="table align-items-center table-flush table-hover mt-3">
|
||||
<thead>
|
||||
<tr class="bg-body-highlight">
|
||||
<th>{% trans "Timestamp" %}</th>
|
||||
<th>{% trans "User" %}</th>
|
||||
<th>{% trans "Action" %}</th>
|
||||
<th>{% trans "Model" %}</th>
|
||||
<th>{% trans "Object ID" %}</th>
|
||||
<th>{% trans "Object Representation" %}</th>
|
||||
<th>{% trans "Field" %}</th> {# Dedicated column for field name #}
|
||||
<th>{% trans "Old Value" %}</th> {# Dedicated column for old value #}
|
||||
<th>{% trans "New Value" %}</th> {# Dedicated column for new value #}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for event in page_obj.object_list %}
|
||||
{% if event.field_changes %}
|
||||
{# Loop through each individual field change for this event #}
|
||||
{% for change in event.field_changes %}
|
||||
<tr>
|
||||
{% for change in event.field_changes %}
|
||||
<tr>
|
||||
{# Display common event details using rowspan for the first change #}
|
||||
{% if forloop.first %}
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.datetime|date:"Y-m-d H:i:s" }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.user.username|default:"Anonymous" }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.event_type_display }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.model_name|title }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.object_id }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.object_repr }}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% if forloop.first %}
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.datetime|date:"Y-m-d H:i:s" }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.user.username|default:"Anonymous" }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.event_type_display }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.model_name|title }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.object_id }}
|
||||
</td>
|
||||
<td rowspan="{{ event.field_changes|length }}">
|
||||
{{ event.object_repr }}
|
||||
</td>
|
||||
{% endif %}
|
||||
|
||||
{# Display the specific field change details in their own columns #}
|
||||
<td><strong>{{ change.field }}</strong></td>
|
||||
<td>
|
||||
{% if change.old is not None %}
|
||||
<pre style="white-space: pre-wrap; word-break: break-all; font-size: 0.85em; background-color: #f8f9fa; padding: 5px; border-radius: 3px;">{{ change.old }}</pre>
|
||||
{% else %}
|
||||
(None)
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if change.new is not None %}
|
||||
<pre style="white-space: pre-wrap; word-break: break-all; font-size: 0.85em; background-color: #f8f9fa; padding: 5px; border-radius: 3px;">{{ change.new }}</pre>
|
||||
{% else %}
|
||||
(None)
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<td><strong>{{ change.field }}</strong></td>
|
||||
<td>
|
||||
{% if change.old is not None %}
|
||||
<pre style="white-space: pre-wrap; word-break: break-all; font-size: 0.85em; background-color: #f8f9fa; padding: 5px; border-radius: 3px;">{{ change.old }}</pre>
|
||||
{% else %}
|
||||
(None)
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if change.new is not None %}
|
||||
<pre style="white-space: pre-wrap; word-break: break-all; font-size: 0.85em; background-color: #f8f9fa; padding: 5px; border-radius: 3px;">{{ change.new }}</pre>
|
||||
{% else %}
|
||||
(None)
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{# Fallback for events with no specific field changes (e.g., CREATE, DELETE) #}
|
||||
<tr>
|
||||
<td>{{ event.datetime|date:"Y-m-d H:i:s" }}</td>
|
||||
@ -94,7 +94,7 @@
|
||||
<td>{{ event.object_id }}</td>
|
||||
<td>{{ event.object_repr }}</td>
|
||||
{# Span the 'Field', 'Old Value', 'New Value' columns #}
|
||||
<td colspan="3">
|
||||
<td>
|
||||
{% if event.event_type_display == "Create" %}
|
||||
{% trans "Object created." %}
|
||||
{% elif event.event_type_display == "Delete" %}
|
||||
@ -110,6 +110,8 @@
|
||||
</table>
|
||||
|
||||
</div>
|
||||
{% include 'partials/pagination_audit.html' with q='userActions' %}
|
||||
|
||||
{% else %}
|
||||
<p>{% trans "No model change audit events found." %}</p>
|
||||
{% endif %}
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
{% load i18n %}
|
||||
<ul class="nav nav-tabs" id="accountTypeTabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
|
||||
<li class="nav-item me-3" role="presentation">
|
||||
<a href="{% url 'audit_log_dashboard' %}?q=userActions">
|
||||
<i class="fas fa-wallet me-2"></i>{% trans "User Actions" %}
|
||||
<i class="fas fa-history me-2"></i>{% trans "User Actions" %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<li class="nav-item me-3" role="presentation">
|
||||
<a href="{% url 'audit_log_dashboard' %}?q=loginEvents">
|
||||
<i class="fas fa-boxes me-2"></i>{% trans "User LoginEvents" %}
|
||||
<i class="fas fa-right-to-bracket me-2"></i>{% trans "User Login Events" %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<a href="{% url 'audit_log_dashboard' %}?q=userRequests">
|
||||
<i class="fas fa-landmark me-2"></i>{% trans "User PageRequests" %}
|
||||
<i class="fas fa-file-alt me-2"></i>{% trans "User Page Requests" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
<div class="tab-content p-3 border border-top-0 rounded-bottom" id="accountTypeTabsContent">
|
||||
<!-- modellogs Tab -->
|
||||
{% if request_events %}
|
||||
{% if page_obj %}
|
||||
<div class="table-responsive px-1 scrollbar mt-3">
|
||||
<table class= "table align-items-center table-flush table-hover">
|
||||
<thead>
|
||||
@ -34,7 +34,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="list">
|
||||
{% for event in request_events %}
|
||||
{% for event in page_obj.object_list %}
|
||||
<tr class="hover-actions-trigger btn-reveal-trigger position-static">
|
||||
|
||||
<td class="align-middle product white-space-nowrap">{{event.datetime}}</td>
|
||||
@ -48,7 +48,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% include 'partials/pagination_audit.html' with q='userRequests' %}
|
||||
{% else %}
|
||||
<p>No request audit events found.</p>
|
||||
{% endif %}
|
||||
|
||||
32
templates/partials/pagination_audit.html
Normal file
32
templates/partials/pagination_audit.html
Normal file
@ -0,0 +1,32 @@
|
||||
{% load i18n static %}
|
||||
|
||||
<div class="row align-items-center justify-content-center py-4 pe-0 fs-9">
|
||||
<div class="col-auto d-flex">
|
||||
{# Previous Button #}
|
||||
{% if page_obj.has_previous %}
|
||||
<a class="page-link" href="?page={{ page_obj.previous_page_number }}{% if q %}&q={{q}}{% endif %}" aria-label="{% trans 'Previous' %}">
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}right{% else %}left{% endif %}" aria-hidden="true"></span>
|
||||
<span>{% trans "Previous" %}</span>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="page-link disabled" aria-disabled="true">
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}right{% else %}left{% endif %}" aria-hidden="true"></span>
|
||||
<span>{% trans "Previous" %}</span>
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{# Next Button #}
|
||||
{% if page_obj.has_next %}
|
||||
<a class="page-link" href="?page={{ page_obj.next_page_number }}{% if q %}&q={{q}}{% endif %}" aria-label="{% trans 'Next' %}">
|
||||
<span>{% trans "Next" %}</span>
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}left{% else %}right{% endif %}" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="page-link disabled" aria-disabled="true">
|
||||
<span>{% trans "Next" %}</span>
|
||||
<span class="fas fa-chevron-{% if LANGUAGE_CODE == 'ar' %}left{% else %}right{% endif %}" aria-hidden="true"></span>
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
Loading…
x
Reference in New Issue
Block a user