Add button for bumping serial

This commit is contained in:
ponas committed 2026-06-10 00:40:17 +02:00
1 parent 5c275dd1e7
commit 9e065f37c2
2 files changed
+60 -5

No files matched your search

+14 -4
View File
@@ -6,7 +6,7 @@ from django.db import models
from django.db.models import Count from django.db.models import Count
from django.forms import NumberInput from django.forms import NumberInput
from mdb.forms import InterfaceForm from mdb.forms import InterfaceForm, SerialNumberInput
from mdb.models import ( from mdb.models import (
DhcpConfig, DhcpConfig,
DhcpCustomField, DhcpCustomField,
@@ -32,6 +32,16 @@ from mdb.models import (
admin.site.site_header = settings.ADMIN_SITE_NAME admin.site.site_header = settings.ADMIN_SITE_NAME
class SerialFieldAdminMixin:
"""Render the ``domain_serial`` field with the wide serial widget + button."""
def formfield_for_dbfield(self, db_field, request, **kwargs):
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
if db_field.name == "domain_serial":
formfield.widget = SerialNumberInput()
return formfield
class Ip6AddressInline(admin.TabularInline): class Ip6AddressInline(admin.TabularInline):
model = Ip6Address model = Ip6Address
extra = 0 extra = 0
@@ -169,7 +179,7 @@ class DhcpCustomFieldInline(admin.TabularInline):
extra = 0 extra = 0
class Ip4SubnetAdmin(admin.ModelAdmin): class Ip4SubnetAdmin(SerialFieldAdminMixin, admin.ModelAdmin):
list_display = [ list_display = [
"name", "name",
"network", "network",
@@ -209,7 +219,7 @@ class Ip4SubnetAdmin(admin.ModelAdmin):
return super(Ip4SubnetAdmin, self).get_queryset(request) return super(Ip4SubnetAdmin, self).get_queryset(request)
class Ip6SubnetAdmin(admin.ModelAdmin): class Ip6SubnetAdmin(SerialFieldAdminMixin, admin.ModelAdmin):
list_display = [ list_display = [
"name", "name",
"network", "network",
@@ -266,7 +276,7 @@ class DomainAAAARecordInline(admin.TabularInline):
extra = 0 extra = 0
class DomainAdmin(admin.ModelAdmin): class DomainAdmin(SerialFieldAdminMixin, admin.ModelAdmin):
inlines = [ inlines = [
DomainSrvRecordInline, DomainSrvRecordInline,
DomainTxtRecordInline, DomainTxtRecordInline,
+46 -1
View File
@@ -1,10 +1,55 @@
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms import ModelChoiceField from django.forms import ModelChoiceField, NumberInput
from django.utils.safestring import mark_safe
from mdb.models import Interface, Ip4Address from mdb.models import Interface, Ip4Address
class SerialNumberInput(NumberInput):
"""Number input for DNS SOA serials (YYYYMMDDXX).
Renders wide enough to show the full 10-digit serial and adds a button
that prefills the field with today's date plus the next available XX
counter (incrementing if the field already holds today's serial).
"""
def __init__(self, attrs=None):
default_attrs = {"style": "width: 12em"}
if attrs:
default_attrs.update(attrs)
super().__init__(default_attrs)
def render(self, name, value, attrs=None, renderer=None):
field = super().render(name, value, attrs, renderer)
field_id = (attrs or {}).get("id", "id_%s" % name)
extra = """
<button type="button" class="button" style="margin-left: 0.5em;"
onclick="mdbBumpSerial('__ID__')">Today + next serial</button>
<script>
if (typeof window.mdbBumpSerial === 'undefined') {
window.mdbBumpSerial = function (inputId) {
var input = document.getElementById(inputId);
if (!input) { return; }
var now = new Date();
var today = '' + now.getFullYear()
+ String(now.getMonth() + 1).padStart(2, '0')
+ String(now.getDate()).padStart(2, '0');
var current = (input.value || '').trim();
var xx = 1;
if (current.length === 10 && current.slice(0, 8) === today) {
xx = Math.min(parseInt(current.slice(8), 10) + 1, 99);
}
input.value = today + String(xx).padStart(2, '0');
};
}
</script>
""".replace(
"__ID__", field_id
)
return mark_safe(field + extra)
class Ip4ModelChoiceField(ModelChoiceField): class Ip4ModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj): def label_from_instance(self, obj):
if not hasattr(obj, "interface"): if not hasattr(obj, "interface"):