Files
igny8/backend/igny8_core/admin/site.py
2025-12-14 21:23:07 +00:00

204 lines
7.4 KiB
Python

"""
Custom AdminSite for IGNY8 to organize models into proper groups using Unfold
NO EMOJIS - Unfold handles all icons via Material Design
"""
from django.contrib import admin
from django.contrib.admin.apps import AdminConfig
from django.apps import apps
from django.urls import path, reverse_lazy
from django.shortcuts import redirect
from django.contrib.admin import sites
from unfold.admin import ModelAdmin as UnfoldModelAdmin
from unfold.sites import UnfoldAdminSite
class Igny8AdminSite(UnfoldAdminSite):
"""
Custom AdminSite based on Unfold that organizes models into the planned groups
"""
site_header = 'IGNY8 Administration'
site_title = 'IGNY8 Admin'
index_title = 'IGNY8 Administration'
def get_urls(self):
"""Get admin URLs without custom dashboard"""
urls = super().get_urls()
return urls
def each_context(self, request):
"""
Override context to ensure our custom app_list is always used
This is called by all admin templates for sidebar rendering
"""
context = super().each_context(request)
# Force our custom app list to be used everywhere
context['available_apps'] = self.get_app_list(request)
return context
def get_app_list(self, request, app_label=None):
"""
Customize the app list to organize models into logical groups
NO EMOJIS - Unfold handles all icons via Material Design
Args:
request: The HTTP request
app_label: Optional app label to filter (used for app index pages)
"""
# Get the default app list
app_dict = self._build_app_dict(request, app_label)
# Define our custom groups with their models (using object_name)
# Organized by business function - Material icons configured in Unfold
custom_groups = {
'Accounts & Users': {
'models': [
('igny8_core_auth', 'Account'),
('igny8_core_auth', 'User'),
('igny8_core_auth', 'Site'),
('igny8_core_auth', 'Sector'),
('igny8_core_auth', 'SiteUserAccess'),
('igny8_core_auth', 'Plan'),
('igny8_core_auth', 'Subscription'),
('igny8_core_auth', 'PasswordResetToken'),
('igny8_core_auth', 'Industry'),
('igny8_core_auth', 'IndustrySector'),
('igny8_core_auth', 'SeedKeyword'),
],
},
'Billing & Tenancy': {
'models': [
('billing', 'Invoice'),
('billing', 'Payment'),
('billing', 'CreditTransaction'),
('billing', 'CreditUsageLog'),
('billing', 'CreditPackage'),
('billing', 'PaymentMethodConfig'),
('billing', 'AccountPaymentMethod'),
('billing', 'CreditCostConfig'),
('billing', 'PlanLimitUsage'),
],
},
'Writer Module': {
'models': [
('writer', 'Content'),
('writer', 'Tasks'),
('writer', 'Images'),
('writer', 'ContentTaxonomy'),
('writer', 'ContentAttribute'),
('writer', 'ContentTaxonomyRelation'),
('writer', 'ContentClusterMap'),
],
},
'Planner': {
'models': [
('planner', 'Clusters'),
('planner', 'Keywords'),
('planner', 'ContentIdeas'),
],
},
'Publishing': {
'models': [
('publishing', 'PublishingRecord'),
('publishing', 'DeploymentRecord'),
],
},
'Optimization': {
'models': [
('optimization', 'OptimizationTask'),
],
},
'Automation': {
'models': [
('automation', 'AutomationConfig'),
('automation', 'AutomationRun'),
],
},
'Integration': {
'models': [
('integration', 'SiteIntegration'),
('integration', 'SyncEvent'),
],
},
'AI Framework': {
'models': [
('ai', 'AITaskLog'),
],
},
'System Configuration': {
'models': [
('system', 'AIPrompt'),
('system', 'Strategy'),
('system', 'AuthorProfile'),
('system', 'ContentTemplate'),
('system', 'TaxonomyConfig'),
('system', 'SystemSetting'),
('system', 'ContentTypeConfig'),
('system', 'PublishingChannel'),
('system', 'APIKey'),
('system', 'WebhookConfig'),
('system', 'NotificationConfig'),
('system', 'AuditLog'),
],
},
'Celery Results': {
'models': [
('django_celery_results', 'TaskResult'),
('django_celery_results', 'GroupResult'),
],
},
'Content Types': {
'models': [
('contenttypes', 'ContentType'),
],
},
'Administration': {
'models': [
('admin', 'LogEntry'),
],
},
'Authentication and Authorization': {
'models': [
('auth', 'Group'),
('auth', 'Permission'),
],
},
'Sessions': {
'models': [
('sessions', 'Session'),
],
},
}
# ALWAYS build and return our custom organized app list
# regardless of app_label parameter (for consistent sidebar on all pages)
organized_apps = []
for group_name, group_config in custom_groups.items():
group_models = []
for app_label, model_name in group_config['models']:
# Find the model in app_dict
for app in app_dict.values():
if app['app_label'] == app_label:
for model in app.get('models', []):
if model['object_name'] == model_name:
group_models.append(model)
break
if group_models:
# Get the first model's app_label to use as the real app_label
first_model_app_label = group_config['models'][0][0]
organized_apps.append({
'name': group_name,
'app_label': first_model_app_label, # Use real app_label, not fake one
'app_url': f'/admin/{first_model_app_label}/', # Real URL, not '#'
'has_module_perms': True,
'models': group_models,
})
return organized_apps
# Instantiate custom admin site
admin_site = Igny8AdminSite(name='admin')