audit log ui
This commit is contained in:
parent
5395f0ab3b
commit
20bb990049
6 changed files with 85 additions and 70 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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" %}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue