audit log ui

This commit is contained in:
Your Name 2023-06-19 12:30:39 -04:00 committed by Henri Dickson
parent 5395f0ab3b
commit 20bb990049
6 changed files with 85 additions and 70 deletions

View file

@ -344,8 +344,12 @@ class Item(SoftDeleteMixin, PolymorphicModel):
)
def merge_to(self, to_item):
self.log_action({"!merged": [str(self.merged_to_item), str(to_item)]})
if to_item is None:
raise ValueError("cannot merge to an empty item")
if self.merged_to_item is not None:
self.merged_to_item = None
self.save()
return
elif to_item.merged_to_item is not None:
raise ValueError("cannot merge with an item aleady merged")
if to_item.__class__ != self.__class__:
@ -377,8 +381,7 @@ class Item(SoftDeleteMixin, PolymorphicModel):
obj,
action=LogEntry.Action.UPDATE,
changes={
"polymorphic_ctype_id": [old_ct.id, ct.id],
"__model__": [old_ct.model, ct.model],
"!recast": [[old_ct.model, old_ct.id], [ct.model, ct.id]],
},
)
return obj

View file

@ -65,7 +65,7 @@ def fetch(request, url, is_refetch: bool = False, site: AbstractSite | None = No
if item and is_refetch:
item.log_action(
{
"__refetch__": [url, None],
"!refetch": [url, None],
}
)
job_id = enqueue_fetch(url, is_refetch)

View file

@ -5,14 +5,42 @@
{% load oauth_token %}
{% load truncate %}
{% if item %}
<h5>进阶编辑选项</h5>
{% if item.is_deleted %}<p>🚫 条目已被删除</p>{% endif %}
{% if item.child_items %}<p>🚫 条目下已有子项</p>{% endif %}
{% if item.merged_to_item %}<p>🚫 条目已被合并到其他条目</p>{% endif %}
{% if item.journal_exists %}<p>🚸 条目已被用户标记过</p>{% endif %}
<div class="action">
<span>
<a title="编辑条目" href="{% url 'catalog:edit' item.url_path item.uuid %}"><i class="fa-solid fa-pencil"></i></a>
</span>
<span>
<a title="编辑历史"
href="{% url 'catalog:history' item.url_path item.uuid %}"><i class="fa-solid fa-clock-rotate-left"></i></a>
</span>
<span>
<a title="返回条目" href="{{ item.url }}"><i class="fa-solid fa-info"></i></a>
</span>
</div>
<h5>编辑选项</h5>
{% if item.is_deleted %}
<p>
<i class="fa-solid fa-circle-xmark"></i> 条目已被删除
</p>
{% endif %}
{% if item.child_items %}
<p>
<i class="fa-solid fa-circle-exclamation"></i> 条目下已有子项
</p>
{% endif %}
{% if item.merged_to_item %}
<p>
<i class="fa-solid fa-circle-xmark"></i> 条目已被合并到其他条目
</p>
{% endif %}
{% if item.journal_exists %}
<p>
<i class="fa-solid fa-circle-exclamation"></i> 条目已被用户标记过
</p>
{% endif %}
{% for i in item.merged_from_items.all %}
{% if forloop.first %}
🚸 以下条目被并入本条目:
<i class="fa-solid fa-circle-info"></i> 以下条目被并入本条目:
<ul>
{% endif %}
<li>
@ -21,7 +49,7 @@
{% if forloop.last %}</ul>{% endif %}
{% endfor %}
{% if item.editable or request.user.is_staff %}
{% for res in form.instance.external_resources.all %}
{% for res in item.external_resources.all %}
<details>
<summary>
{% trans '源网站' %}: <a href="{{ res.url }}">{{ res.site_name.label }}</a>
@ -56,9 +84,9 @@
</form>
</details>
{% endif %}
<details>
<summary>{% trans '切换分类' %}</summary>
{% if item.class_name == "movie" %}
{% if item.class_name == "movie" %}
<details>
<summary>{% trans '切换分类' %}</summary>
<form method="post"
action="{% url 'catalog:recast' item.url_path item.uuid %}"
onsubmit="return confirm('确认切换吗?');">
@ -66,13 +94,18 @@
<input type="hidden" value="tvshow" name="class">
<input class="contrast" type="submit" value="{% trans '更改为剧集' %}">
</form>
{% elif item.class_name == "tvshow" %}
{% if not item.all_seasons or request.user.is_staff %}
{% comment %} <form method="post" action="{% url 'catalog:recast' item.url_path item.uuid %}" onsubmit="return confirm('确认切换吗?');">
</details>
{% elif item.class_name == "tvshow" %}
{% if not item.all_seasons or request.user.is_staff %}
<details>
<summary>{% trans '切换分类' %}</summary>
<form method="post"
action="{% url 'catalog:recast' item.url_path item.uuid %}"
onsubmit="return confirm('确认切换吗?');">
{% csrf_token %}
<input type="hidden" value="movie" name="class">
<input class="contrast" type="submit" value="{% trans '更改为电影' %}">
</form> {% endcomment %}
</form>
<form method="post"
action="{% url 'catalog:recast' item.url_path item.uuid %}"
onsubmit="return confirm('确认切换吗?');">
@ -80,11 +113,11 @@
<input type="hidden" value="tvseason" name="class">
<input class="contrast" type="submit" value="{% trans '更改为单季' %}">
</form>
{% endif %}
{% else %}
<i>此类条目无法切换</i>
</details>
{% endif %}
</details>
{% else %}
<!--此类条目无法切换-->
{% endif %}
{% if item.class_name == "tvseason" or item.class_name == "performanceproduction" %}
{% if not item.show or request.user.is_staff %}
<details>
@ -129,13 +162,13 @@
<input class="contrast" type="submit" value="{% trans '合并到同类另一条目' %}">
</form>
</details>
<details>
<summary>{% trans '删除' %}</summary>
{% if item.class_name == "tvshow" and item.all_seasons %}
<i>⛔️ 条目下有子项</i>
{% elif item.merged_from_items.all %}
<i>⛔️ 有其他条目被并入</i>
{% else %}
{% if item.child_items %}
<!-- 条目下有子项 -->
{% elif item.merged_from_items.all %}
<!-- 有其他条目被并入 -->
{% else %}
<details>
<summary>{% trans '删除' %}</summary>
<form method="post"
action="{% url 'catalog:delete' item.url_path item.uuid %}"
onsubmit="return confirm('本操作不可撤销。确认删除吗?');">
@ -145,8 +178,8 @@
{% if item.is_deleted or item.merged_to_item %}disabled{% endif %}
value="{% trans '删除' %}">
</form>
{% endif %}
</details>
</details>
{% endif %}
{% endif %}
{% endif %}
{% endif %}

View file

@ -53,39 +53,6 @@
onclick="{% if item %}window.location='{{ item.url }}'{% else %}history.go(-1){% endif %}">
</div>
</form>
{% if request.user.is_staff %}
<div>
<table class="table table-striped table-bordered">
<thead>
<tr style="background:#eee;">
<th>Field</th>
<th style="width:40%;padding-right: 8px;">From</th>
<th style="width:40%;">To</th>
</tr>
</thead>
<tbody>
{% for log in item.history.all %}
<tr>
<td colspan="3">
({{ log.id }}) <b>{{ log.actor }} {{ log.get_action_display }} on {{ log.timestamp }}</b>
</td>
</tr>
{% for key, value in log.changes_dict.items %}
<tr {% cycle 'style="background:#eee;"' '' %}>
<td>{{ key }}</td>
<td>{{ value.0|default:"-" }}</td>
<td>{{ value.1|default:"-" }}</td>
</tr>
{% empty %}
<p>No data.</p>
{% endfor %}
{% empty %}
<p>No history for this item has been logged yet.</p>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</div>
<aside class="grid__aside">
{% include "_sidebar_edit.html" %}

View file

@ -37,6 +37,13 @@ urlpatterns = [
),
path("podcast/<str:item_uuid>/episodes", episode_data, name="episode_data"),
path("catalog/create/<str:item_model>", create, name="create"),
re_path(
r"^(?P<item_path>"
+ _get_all_url_paths()
+ ")/(?P<item_uuid>[A-Za-z0-9]{21,22})/history$",
history,
name="history",
),
re_path(
r"^(?P<item_path>"
+ _get_all_url_paths()

View file

@ -1,5 +1,4 @@
import logging
from django.contrib import messages
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required, permission_required
from django.utils.translation import gettext_lazy as _
@ -23,9 +22,7 @@ from journal.models import ShelfTypeNames, ShelfType, ItemCategory
from .forms import *
from .search.views import *
from django.http import Http404
from management.models import Announcement
from django.core.cache import cache
import random
_logger = logging.getLogger(__name__)
@ -184,6 +181,15 @@ def create(request, item_model):
raise BadRequest("Invalid request method")
@login_required
def history(request, item_path, item_uuid):
if request.method == "GET":
item = get_object_or_404(Item, uid=get_uuid_or_404(item_uuid))
return render(request, "catalog_history.html", {"item": item})
else:
raise BadRequest()
@login_required
def edit(request, item_path, item_uuid):
if request.method == "GET":
@ -313,7 +319,7 @@ def remove_unused_seasons(request, item_path, item_uuid):
s.delete()
l = [s.id for s in l]
l2 = [s.id for s in item.seasons.all()]
item.log_action({"__remove_unused_seasons__": [l, l2]})
item.log_action({"!remove_unused_seasons": [l, l2]})
return redirect(item.url)
@ -339,8 +345,7 @@ def merge(request, item_path, item_uuid):
else:
if item.merged_to_item:
_logger.warn(f"{request.user} cancels merge for {item}")
item.merged_to_item = None
item.save()
item.merge_to(None)
return redirect(item.url)