diff --git a/backend/igny8_core/admin/site_backup.py b/backend/igny8_core/admin/site_backup.py new file mode 100644 index 00000000..713d8e7f --- /dev/null +++ b/backend/igny8_core/admin/site_backup.py @@ -0,0 +1,179 @@ +""" +Custom AdminSite for IGNY8 to organize models into proper groups using Unfold +""" +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 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 get_app_list(self, request): + """ + Customize the app list to organize models into logical groups + """ + # Get the default app list + app_dict = self._build_app_dict(request) + + # Define our custom groups with their models (using object_name) + # Organized by business function with emoji icons for visual recognition + custom_groups = { + '💰 Billing & Accounts': { + 'models': [ + ('igny8_core_auth', 'Plan'), + ('billing', 'PlanLimitUsage'), + ('igny8_core_auth', 'Account'), + ('igny8_core_auth', 'Subscription'), + ('billing', 'Invoice'), + ('billing', 'Payment'), + ('billing', 'CreditTransaction'), + ('billing', 'CreditUsageLog'), + ('billing', 'CreditPackage'), + ('billing', 'PaymentMethodConfig'), + ('billing', 'AccountPaymentMethod'), + ('billing', 'CreditCostConfig'), + ], + }, + '👥 Sites & Users': { + 'models': [ + ('igny8_core_auth', 'Site'), + ('igny8_core_auth', 'Sector'), + ('igny8_core_auth', 'User'), + ('igny8_core_auth', 'SiteUserAccess'), + ('igny8_core_auth', 'PasswordResetToken'), + ], + }, + '📚 Content Management': { + 'models': [ + ('writer', 'Content'), + ('writer', 'Tasks'), + ('writer', 'Images'), + ('writer', 'ContentTaxonomy'), + ('writer', 'ContentAttribute'), + ('writer', 'ContentTaxonomyRelation'), + ('writer', 'ContentClusterMap'), + ], + }, + '🎯 Planning & Strategy': { + 'models': [ + ('planner', 'Clusters'), + ('planner', 'Keywords'), + ('planner', 'ContentIdeas'), + ('system', 'Strategy'), + ], + }, + '🔗 Integrations & Publishing': { + 'models': [ + ('integration', 'SiteIntegration'), + ('integration', 'SyncEvent'), + ('publishing', 'PublishingRecord'), + ('publishing', 'DeploymentRecord'), + ], + }, + '🤖 AI & Automation': { + 'models': [ + ('ai', 'AITaskLog'), + ('system', 'AIPrompt'), + ('automation', 'AutomationConfig'), + ('automation', 'AutomationRun'), + ('optimization', 'OptimizationTask'), + ], + }, + '🌍 Global Reference Data': { + 'models': [ + ('igny8_core_auth', 'Industry'), + ('igny8_core_auth', 'IndustrySector'), + ('igny8_core_auth', 'SeedKeyword'), + ], + }, + '⚙️ System Configuration': { + 'models': [ + ('system', 'IntegrationSettings'), + ('system', 'AuthorProfile'), + ('system', 'SystemSettings'), + ('system', 'AccountSettings'), + ('system', 'UserSettings'), + ('system', 'ModuleSettings'), + ('system', 'AISettings'), + ('system', 'ModuleEnableSettings'), + ('system', 'SystemLog'), + ('system', 'SystemStatus'), + ], + }, + '� Monitoring & Tasks': { + 'models': [ + ('django_celery_results', 'TaskResult'), + ('django_celery_results', 'GroupResult'), + ], + }, + '�🔧 Django System': { + 'models': [ + ('admin', 'LogEntry'), + ('auth', 'Group'), + ('auth', 'Permission'), + ('contenttypes', 'ContentType'), + ('sessions', 'Session'), + ], + }, + } + + # Build the custom app list + app_list = [] + + 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 + if app_label in app_dict: + app_data = app_dict[app_label] + # Look for the model in the app's models + for model in app_data.get('models', []): + if model['object_name'] == model_name: + group_models.append(model) + break + + # Only add the group if it has models + if group_models: + app_list.append({ + 'name': group_name, + 'app_label': group_name.lower().replace(' ', '_').replace('&', '').replace('emoji', ''), + 'app_url': None, + 'has_module_perms': True, + 'models': group_models, + }) + + # Sort the app list by our custom order + order = [ + '💰 Billing & Accounts', + '👥 Sites & Users', + '📚 Content Management', + '🎯 Planning & Strategy', + '🔗 Integrations & Publishing', + '🤖 AI & Automation', + '🌍 Global Reference Data', + '⚙️ System Configuration', + '🔧 Django System', + ] + + app_list.sort(key=lambda x: order.index(x['name']) if x['name'] in order else 999) + + return app_list + + + diff --git a/backend/igny8_core/auth/admin.py b/backend/igny8_core/auth/admin.py index 756014fa..ea306f01 100644 --- a/backend/igny8_core/auth/admin.py +++ b/backend/igny8_core/auth/admin.py @@ -178,15 +178,12 @@ class AccountAdmin(AccountAdminMixin, ModelAdmin): # Check credits if obj.credits < 10: status = 'critical' - icon = '🔴' message = 'Critical: Very low credits' elif obj.credits < 100: status = 'warning' - icon = '⚠️' message = 'Warning: Low credits' else: status = 'good' - icon = '✅' message = 'Good' # Check for recent failed automations @@ -201,12 +198,10 @@ class AccountAdmin(AccountAdminMixin, ModelAdmin): if failed_runs > 5: status = 'critical' - icon = '🔴' message = f'Critical: {failed_runs} automation failures' elif failed_runs > 0: if status == 'good': status = 'warning' - icon = '⚠️' message = f'Warning: {failed_runs} automation failures' except: pass @@ -214,7 +209,6 @@ class AccountAdmin(AccountAdminMixin, ModelAdmin): # Check account status if obj.status != 'active': status = 'critical' - icon = '🔴' message = f'Critical: Account {obj.status}' colors = { @@ -224,8 +218,8 @@ class AccountAdmin(AccountAdminMixin, ModelAdmin): } return format_html( - '{} {}', - icon, colors[status], message + '{}', + colors[status], message ) health_indicator.short_description = 'Health' @@ -238,12 +232,18 @@ class AccountAdmin(AccountAdminMixin, ModelAdmin): details = [] # Credits status + colors = { + 'critical': '#ef4444', + 'warning': '#ff7a00', + 'good': '#0bbf87' + } + if obj.credits < 10: - details.append(f'🔴 Critical: Only {obj.credits} credits remaining') + details.append(f'Critical: Only {obj.credits} credits remaining') elif obj.credits < 100: - details.append(f'⚠️ Warning: Only {obj.credits} credits remaining') + details.append(f'Warning: Only {obj.credits} credits remaining') else: - details.append(f'✅ Credits: {obj.credits} available') + details.append(f'Credits: {obj.credits} available') # Recent activity try: