[UPDT] BASE: Added history for models using django audit log
This commit is contained in:
@@ -9,4 +9,4 @@
|
||||
</div>
|
||||
{{ form.is_enable.errors }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -5,7 +5,11 @@ This module is used to write methods related to the history
|
||||
"""
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.paginator import Paginator
|
||||
from django.db import models
|
||||
from django.shortcuts import render
|
||||
|
||||
from horilla.decorators import apply_decorators
|
||||
|
||||
|
||||
class Bot:
|
||||
@@ -146,3 +150,27 @@ def get_diff(instance):
|
||||
if track_fields:
|
||||
delta_changes = filter_history(delta_changes, track_fields)
|
||||
return delta_changes
|
||||
|
||||
|
||||
def history_tracking(request, obj_id, **kwargs):
|
||||
model = kwargs.get("model")
|
||||
decorator_strings = kwargs.get("decorators", [])
|
||||
|
||||
@apply_decorators(decorator_strings)
|
||||
def _history_tracking(request, obj_id, model):
|
||||
instance = model.objects.get(pk=obj_id)
|
||||
histories = instance.horilla_history.all()
|
||||
page_number = request.GET.get("page", 1)
|
||||
paginator = Paginator(histories, 4)
|
||||
page_obj = paginator.get_page(page_number)
|
||||
context = {
|
||||
"histories": page_obj,
|
||||
"model_name": model,
|
||||
}
|
||||
return render(
|
||||
request,
|
||||
"horilla_audit/history_tracking.html",
|
||||
context,
|
||||
)
|
||||
|
||||
return _history_tracking(request, obj_id, model)
|
||||
|
||||
144
horilla_audit/templates/horilla_audit/history_tracking.html
Normal file
144
horilla_audit/templates/horilla_audit/history_tracking.html
Normal file
@@ -0,0 +1,144 @@
|
||||
{% load static %} {% load i18n %} {% load audit_filters %}
|
||||
<div class="oh-activity-sidebar__header" style="position:sticky; top:0; background:#fff; z-index:10">
|
||||
<a
|
||||
style="cursor: pointer"
|
||||
onclick="$('.oh-activity-sidebar--show').removeClass('oh-activity-sidebar--show');"
|
||||
>
|
||||
<ion-icon
|
||||
name="chevron-forward-outline"
|
||||
class="oh-activity-sidebar__header-icon me-2 oh-activity-sidebar__close md hydrated"
|
||||
data-target="#activitySidebar"
|
||||
role="img"
|
||||
aria-label="chevron forward outline"
|
||||
></ion-icon>
|
||||
</a>
|
||||
<h1 class="oh-main__titlebar-title fw-bold ml-3 mb-3 mt-3">
|
||||
{{model_name|verbose_name}} {% trans "History" %}
|
||||
</h1>
|
||||
</div>
|
||||
<div style="height:60vh; overflow-y:auto" id="infiniteContainer">
|
||||
<div class="row" style="" id = "infinite">
|
||||
{% if histories %} {% for history in histories %}
|
||||
<div class="oh-history__container item">
|
||||
<div
|
||||
class="oh-history_date oh-card__title oh-card__title--sm fw-bold me-2"
|
||||
>
|
||||
<span class="oh-history_date-content">
|
||||
<span class="dateformat_changer"
|
||||
>{{ history.timestamp|date:"M. d, Y" }}</span
|
||||
> , 
|
||||
<span class="timeformat_changer"
|
||||
>{{ history.timestamp|date:"g:i A" }}</span
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<div class="oh-history_user-img">
|
||||
{% if history.actor.employee_get %}
|
||||
<img
|
||||
src="{{history.actor.employee_get.get_avatar}}"
|
||||
alt=""
|
||||
class="oh-history_user-pic"
|
||||
/>
|
||||
{% else %}
|
||||
<img
|
||||
src="https://ui-avatars.com/api/?name=Horilla+Bot&background=random"
|
||||
alt=""
|
||||
class="oh-history_user-pic"
|
||||
/>
|
||||
{% endif %}
|
||||
<div class="oh-history_user-state oh-user_inactive"></div>
|
||||
</div>
|
||||
|
||||
<div class="oh-history_user-details">
|
||||
<span class="oh-history__username"
|
||||
>{% if history.actor.employee_get %} {{history.actor.employee_get.get_full_name}} {% else %} Horilla Bot {% endif %}</span
|
||||
>
|
||||
<div class="oh-history_abt pb-0">
|
||||
<span class="oh-history_task-state">
|
||||
{% if history.action == 0 %}
|
||||
{% trans "Created" %} {{model_name|verbose_name}}
|
||||
{% elif history.action == 1 %}
|
||||
{% trans "Updated" %} {{model_name|verbose_name}}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="oh-history_msg-container">
|
||||
<div class="oh-history_task-tracker">
|
||||
<ul class="ul">
|
||||
{% for change,value in history.changes_dict.items %}
|
||||
{% if value.type == 'm2m' %}
|
||||
<li class="oh-history_task-list">
|
||||
<div class="oh-history_track-value">
|
||||
<span>{{model_name|verbose_name:change}}</span>
|
||||
<img
|
||||
src="{% static '/images/ui/arrow-right-line.svg' %}"
|
||||
class="oh-progress_arrow"
|
||||
alt=""
|
||||
/>
|
||||
<span class="oh-history-task-state"
|
||||
><i
|
||||
>{{value.objects|join:", "}}</i
|
||||
></span
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for change,value in history.changes_display_dict.items %}
|
||||
{% if not value.0 == "type" %}
|
||||
<li class="oh-history_task-list">
|
||||
<div class="oh-history_track-value">
|
||||
<span>{{change}}</span>
|
||||
<span class="oh-history_tracking-value"
|
||||
><i>({{value.0}})</i></span
|
||||
>
|
||||
<img
|
||||
src="{% static '/images/ui/arrow-right-line.svg' %}"
|
||||
class="oh-progress_arrow"
|
||||
alt=""
|
||||
/>
|
||||
<span class="oh-history-task-state"
|
||||
><i>({{value.1}})</i></span
|
||||
>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if histories.has_next and forloop.last %}
|
||||
<div class="scrollButton" hx-get="{{request.META.PATH_INFO}}?page={{ histories.next_page_number }}"
|
||||
hx-swap="beforeend" hx-target="#infinite" hx-select=".item"
|
||||
>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<div
|
||||
class="d-flex justify-content-center align-items-center"
|
||||
style="height: 40vh"
|
||||
>
|
||||
<h5 class="oh-404__subtitle">{% trans "No history found." %}</h5>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.body.addEventListener('htmx:load', function(evt) {
|
||||
var container ="#infiniteContainer";
|
||||
var $container = $(container)
|
||||
var $lastItem = $('.row .item .scrollButton').last();
|
||||
|
||||
$container.on('scroll', function() {
|
||||
if ($container[0].scrollTop + $container[0].clientHeight + 2 >= $container[0].scrollHeight) {
|
||||
$lastItem.click();
|
||||
$lastItem.remove()
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1,9 +1,5 @@
|
||||
from django import template
|
||||
from django.core.paginator import Page, Paginator
|
||||
from django.template.defaultfilters import register
|
||||
|
||||
from employee.models import Employee, EmployeeWorkInformation
|
||||
|
||||
|
||||
@register.filter(name="fk_history")
|
||||
def fk_history(instance, change):
|
||||
@@ -18,3 +14,19 @@ def fk_history(instance, change):
|
||||
value = str(value) + f" (Previous {change['field']} deleted)"
|
||||
pass
|
||||
return value
|
||||
|
||||
|
||||
@register.filter(name="verbose_name")
|
||||
def verbose_name(model, field_name=None):
|
||||
""" "
|
||||
This method is used to fine the verbose name of a field
|
||||
"""
|
||||
if not field_name:
|
||||
model_name = model._meta.verbose_name.capitalize()
|
||||
return model_name
|
||||
|
||||
try:
|
||||
field = model._meta.get_field(field_name)
|
||||
return field.verbose_name
|
||||
except:
|
||||
return field_name
|
||||
|
||||
@@ -441,7 +441,7 @@
|
||||
$(document).on("htmx:beforeRequest", function (event, data) {
|
||||
var response = event.detail.xhr.response;
|
||||
var target = $(event.detail.elt.getAttribute("hx-target"));
|
||||
var avoid_target = ["BiometricDeviceTestFormTarget","reloadMessages"];
|
||||
var avoid_target = ["BiometricDeviceTestFormTarget","reloadMessages", "infinite"];
|
||||
if (!target.closest("form").length && avoid_target.indexOf(target.attr("id")) === -1) {
|
||||
target.html(`<div class="animated-background"></div>`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user