Add report record admin and template search

When creating a ban, you can type in to do a search, this is useful for
quickly banning users.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2022-06-23 18:16:00 -07:00
parent 789bd0efe9
commit b64559aba9
4 changed files with 88 additions and 15 deletions

View File

@@ -1,10 +1,15 @@
from django import forms
from django.contrib import admin from django.contrib import admin
from django.http.response import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from board.models import Ban, Board, Post, RangeBan, ReportReason, ReportRecord from board.models import (
Ban,
BanTemplate,
Board,
Post,
RangeBan,
ReportReason,
ReportRecord,
)
# #
# Admin sites # Admin sites
@@ -24,10 +29,6 @@ class ReportReasonAdmin(admin.ModelAdmin):
pass pass
class BanFromReportForm(forms.ModelForm):
pass
@admin.register(ReportRecord) @admin.register(ReportRecord)
class ReportRecordAdmin(admin.ModelAdmin): class ReportRecordAdmin(admin.ModelAdmin):
ordering = ( ordering = (
@@ -76,3 +77,8 @@ class RangeBanAdmin(admin.ModelAdmin):
@admin.register(Ban) @admin.register(Ban)
class BanAdmin(admin.ModelAdmin): class BanAdmin(admin.ModelAdmin):
pass pass
@admin.register(BanTemplate)
class BanTemplateAdmin(admin.ModelAdmin):
ordering = ("board__url", "name")

View File

@@ -311,11 +311,21 @@ class Ban(BanCommon):
class BanTemplate(models.Model): class BanTemplate(models.Model):
# The name of this template
name = models.CharField(max_length=100)
# The reason for this ban # The reason for this ban
ban_reason = models.TextField(blank=False) ban_reason = models.TextField(blank=False)
# The duration of the ban # The duration of the ban, in days
duration = models.DurationField() duration = models.IntegerField(blank=True, null=True)
# The board that this template is for, or none.
board = models.ForeignKey("Board", on_delete=models.CASCADE, null=True, blank=True)
def create_ban(self, ip: str) -> Ban: def create_ban(self, ip: str) -> Ban:
expires = timezone.now() + self.duration expires = timezone.now() + self.duration
return Ban.objects.create(ip=ip, ban_reason=self.ban_reason, expires=expires) return Ban.objects.create(ip=ip, ban_reason=self.ban_reason, expires=expires)
def __str__(self) -> str:
if self.board:
return f"/{self.board.url}/ - {self.name}"
else:
return self.name

View File

@@ -2,7 +2,7 @@
{% load i18n %} {% load i18n %}
{% block content %} {% block content %}
<form id="form" action="{% url 'board:ban_create' url=board.url id=post.id %}" method="post"> <form id="form" action="{% url 'board:ban_create' url=board.url id=post.id %}" method="post" autocomplete="off">
{% csrf_token %} {% csrf_token %}
<table> <table>
<tr> <tr>
@@ -17,13 +17,28 @@
<th>IP:</th> <th>IP:</th>
<td>{{post.ip}}</td> <td>{{post.ip}}</td>
</tr> </tr>
<tr>
<th>{% translate 'Template search' %}:</th>
<td><input id="template_search" type="text" /></td>
</tr>
<tr>
<th>{% translate 'Template' %}</th>
<td>
<select id="templates">
<option class="template_option" data-reason="" data-duration="">Custom</option>
{% for template in templates %}
<option class="template_option" data-reason="{{template.ban_reason}}" data-duration="{{template.duration}}">{{template.name}}</option>
{% endfor %}
</select>
</td>
</tr>
{{form.as_table}} {{form.as_table}}
<tr> <tr>
<th>{% translate "Previous bans" %}</th> <th>{% translate "Previous bans" %}:</th>
<td>{{previous_bans|length}}</td> <td>{{previous_bans|length}}</td>
</tr> </tr>
<tr> <tr>
<th>{% translate "Current bans" %}</th> <th>{% translate "Current bans" %}:</th>
<td id="current_bans">{{current_bans|length}}</td> <td id="current_bans">{{current_bans|length}}</td>
</tr> </tr>
<tr> <tr>
@@ -35,7 +50,6 @@
<script> <script>
function submitConfirm(e) { function submitConfirm(e) {
console.log($("#current_bans").text());
if($("#current_bans").text() !== '0') { if($("#current_bans").text() !== '0') {
let result = window.confirm("There is already at least one ban for this IP address on this board, are you sure you want to continue?"); let result = window.confirm("There is already at least one ban for this IP address on this board, are you sure you want to continue?");
if (!result) { if (!result) {
@@ -45,6 +59,45 @@ function submitConfirm(e) {
} }
} }
function templateSelect(e) {
let selected = $($(e.target).find(":selected"));
// uh oh, mixing django templates and JS
let banReason = $("#{{form.ban_reason.auto_id}}");
let duration = $("#{{form.duration.auto_id}}");
banReason.val(selected.attr("data-reason"));
duration.val(selected.attr("data-duration"));
if(selected.val() === "Custom") {
// unlock the controls
banReason.attr("readonly", false);
duration.attr("readonly", false);
} else {
// lock all controls
banReason.attr("readonly", true);
duration.attr("readonly", true);
}
}
function templateSearch(e) {
let search = $(e.target).val();
let element = $("#templates option").toArray().find(element => {
let re = new RegExp(search, "i");
return element.value.search(re) !== -1;
});
if(typeof element === "undefined") {
return;
}
$("#templates")
.val(element.value)
.trigger("change");
}
$("#submit").on("click", submitConfirm); $("#submit").on("click", submitConfirm);
$("#templates").on("change", templateSelect);
$("#template_search").on("input propertychange paste", templateSearch);
$("#template_search").select();
</script> </script>
{% endblock content %} {% endblock content %}

View File

@@ -1,6 +1,7 @@
from typing import Any, Dict from typing import Any, Dict
from django.conf import settings from django.conf import settings
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db.models import Q
from django.http import Http404, HttpResponseRedirect from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
@@ -8,7 +9,7 @@ from django.views.generic.edit import CreateView
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
from django.utils import timezone from django.utils import timezone
from board.forms import BanForm, PostForm, ReplyForm, ReportForm from board.forms import BanForm, PostForm, ReplyForm, ReportForm
from board.models import Ban, Board, Post, Report from board.models import Ban, BanTemplate, Board, Post, Report
from board.utils import get_client_ip, get_ip_bans from board.utils import get_client_ip, get_ip_bans
__all__ = ( __all__ = (
@@ -186,6 +187,9 @@ class BanCreateView(PermissionRequiredMixin, CreateView):
context["current_bans"] = [ context["current_bans"] = [
ban for ban in bans if ban.expires is None or ban.expires > now ban for ban in bans if ban.expires is None or ban.expires > now
] ]
context["templates"] = BanTemplate.objects.filter(
Q(board=self.board) | Q(board=None)
)
return context return context