PLugin versioning fixes

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-09 23:36:03 +00:00
parent 4343f62140
commit 0ea3a30909
7 changed files with 441 additions and 115 deletions

View File

@@ -1,6 +1,7 @@
"""
Django Admin Configuration for Plugin Distribution System
"""
from django import forms
from django.contrib import admin
from django.utils.html import format_html
from django.urls import reverse
@@ -8,6 +9,68 @@ from unfold.admin import ModelAdmin, TabularInline
from .models import Plugin, PluginVersion, PluginInstallation, PluginDownload
class PluginVersionForm(forms.ModelForm):
"""
Simplified form for creating new plugin versions.
Auto-fills most fields from the latest version, only requires:
- Plugin (select)
- Version number
- Changelog
- Status (defaults to 'draft')
All other fields are either:
- Auto-filled from previous version (min_api_version, min_php_version, etc.)
- Auto-generated on release (file_path, file_size, checksum)
- Auto-calculated (version_code)
"""
class Meta:
model = PluginVersion
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# If this is a new version (no instance), auto-fill from latest
if not self.instance.pk:
# Check if plugin is already selected (from initial data or POST data)
plugin_id = None
# Try to get plugin from POST data (when form is submitted)
if self.data:
plugin_id = self.data.get('plugin')
# Try to get plugin from initial data (when form is pre-filled)
elif self.initial:
plugin_id = self.initial.get('plugin')
if plugin_id:
try:
plugin = Plugin.objects.get(pk=plugin_id)
latest = plugin.get_latest_version()
if latest:
# Auto-fill from latest version (only if not POST)
if not self.data:
if 'min_api_version' in self.fields:
self.fields['min_api_version'].initial = latest.min_api_version
if 'min_platform_version' in self.fields:
self.fields['min_platform_version'].initial = latest.min_platform_version
if 'min_php_version' in self.fields:
self.fields['min_php_version'].initial = latest.min_php_version
if 'force_update' in self.fields:
self.fields['force_update'].initial = False
except (Plugin.DoesNotExist, ValueError, TypeError):
pass
# Set helpful help texts for fields that exist in the form
# (some fields may be readonly and not in self.fields)
if 'version' in self.fields:
self.fields['version'].help_text = "Semantic version (e.g., 1.2.0)"
if 'changelog' in self.fields:
self.fields['changelog'].help_text = "What's new in this version"
class PluginVersionInline(TabularInline):
"""Inline admin for plugin versions."""
model = PluginVersion
@@ -66,35 +129,37 @@ class PluginAdmin(ModelAdmin):
class PluginVersionAdmin(ModelAdmin):
"""Admin configuration for PluginVersion model."""
form = PluginVersionForm
list_display = ['plugin', 'version', 'status', 'file_size_display', 'download_count', 'released_at']
list_filter = ['plugin', 'status', 'released_at']
search_fields = ['plugin__name', 'version', 'changelog']
readonly_fields = ['version_code', 'created_at', 'download_count']
readonly_fields = ['version_code', 'file_path', 'file_size', 'checksum', 'created_at', 'released_at', 'download_count']
fieldsets = [
('Version Info', {
'fields': ['plugin', 'version', 'version_code', 'status']
('Required Fields', {
'fields': ['plugin', 'version', 'status', 'changelog'],
'description': 'Only these fields are required. Others are auto-filled from previous version or auto-generated.'
}),
('File Info', {
'fields': ['file_path', 'file_size', 'checksum']
}),
('Requirements', {
'fields': ['min_api_version', 'min_platform_version', 'min_php_version']
}),
('Release', {
'fields': ['changelog', 'force_update', 'released_at']
}),
('Statistics', {
'fields': ['download_count'],
('Requirements (Auto-filled from previous version)', {
'fields': ['min_api_version', 'min_platform_version', 'min_php_version'],
'classes': ['collapse']
}),
('Timestamps', {
'fields': ['created_at'],
('File Info (Auto-generated on release)', {
'fields': ['file_path', 'file_size', 'checksum'],
'classes': ['collapse']
}),
('Advanced Options', {
'fields': ['version_code', 'force_update'],
'classes': ['collapse']
}),
('Metadata', {
'fields': ['released_at', 'download_count', 'created_at'],
'classes': ['collapse']
}),
]
actions = ['release_versions', 'mark_as_update_ready']
actions = ['release_versions', 'mark_as_update_ready', 'mark_as_deprecated']
def file_size_display(self, obj):
if obj.file_size:
@@ -109,19 +174,25 @@ class PluginVersionAdmin(ModelAdmin):
return obj.get_download_count()
download_count.short_description = 'Downloads'
@admin.action(description="Release selected versions")
@admin.action(description="Release selected versions (builds ZIP automatically)")
def release_versions(self, request, queryset):
from django.utils import timezone
count = queryset.filter(status__in=['draft', 'testing', 'staged']).update(
status='released',
released_at=timezone.now()
)
self.message_user(request, f"Released {count} version(s)")
count = 0
for version in queryset.filter(status__in=['draft', 'testing', 'staged']):
version.status = 'released'
version.save() # Triggers signal to build ZIP
count += 1
self.message_user(request, f"Released {count} version(s). ZIP files are being built automatically.")
@admin.action(description="Mark as update ready (push to installations)")
@admin.action(description="📢 Mark as update ready (notify WordPress sites)")
def mark_as_update_ready(self, request, queryset):
count = queryset.filter(status='released').update(status='update_ready')
self.message_user(request, f"Marked {count} version(s) as update ready")
self.message_user(request, f"Marked {count} version(s) as update ready. WordPress sites will be notified.")
@admin.action(description="🗑️ Mark as deprecated")
def mark_as_deprecated(self, request, queryset):
count = queryset.update(status='deprecated')
self.message_user(request, f"Marked {count} version(s) as deprecated")
@admin.register(PluginInstallation)