diff --git a/backend/igny8_core/admin/site.py b/backend/igny8_core/admin/site.py index 713d8e7f..eae24bbc 100644 --- a/backend/igny8_core/admin/site.py +++ b/backend/igny8_core/admin/site.py @@ -1,5 +1,6 @@ """ 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 @@ -26,19 +27,31 @@ class Igny8AdminSite(UnfoldAdminSite): def get_app_list(self, request): """ Customize the app list to organize models into logical groups + NO EMOJIS - Unfold handles all icons via Material Design """ # 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 + # Organized by business function - Material icons configured in Unfold custom_groups = { - '💰 Billing & Accounts': { + 'Igny8_Core_Auth': { 'models': [ - ('igny8_core_auth', 'Plan'), - ('billing', 'PlanLimitUsage'), ('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'), @@ -47,18 +60,10 @@ class Igny8AdminSite(UnfoldAdminSite): ('billing', 'PaymentMethodConfig'), ('billing', 'AccountPaymentMethod'), ('billing', 'CreditCostConfig'), + ('billing', 'PlanLimitUsage'), ], }, - '👥 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': { + 'Writer Module': { 'models': [ ('writer', 'Content'), ('writer', 'Tasks'), @@ -69,111 +74,112 @@ class Igny8AdminSite(UnfoldAdminSite): ('writer', 'ContentClusterMap'), ], }, - '🎯 Planning & Strategy': { + 'Planner': { 'models': [ ('planner', 'Clusters'), ('planner', 'Keywords'), ('planner', 'ContentIdeas'), - ('system', 'Strategy'), ], }, - '🔗 Integrations & Publishing': { + 'Publishing': { 'models': [ - ('integration', 'SiteIntegration'), - ('integration', 'SyncEvent'), ('publishing', 'PublishingRecord'), ('publishing', 'DeploymentRecord'), ], }, - '🤖 AI & Automation': { + 'Optimization': { 'models': [ - ('ai', 'AITaskLog'), - ('system', 'AIPrompt'), - ('automation', 'AutomationConfig'), - ('automation', 'AutomationRun'), ('optimization', 'OptimizationTask'), ], }, - '🌍 Global Reference Data': { + 'Automation': { 'models': [ - ('igny8_core_auth', 'Industry'), - ('igny8_core_auth', 'IndustrySector'), - ('igny8_core_auth', 'SeedKeyword'), + ('automation', 'AutomationConfig'), + ('automation', 'AutomationRun'), ], }, - '⚙️ System Configuration': { + 'Integration': { 'models': [ - ('system', 'IntegrationSettings'), + ('integration', 'SiteIntegration'), + ('integration', 'SyncEvent'), + ], + }, + 'AI Framework': { + 'models': [ + ('ai', 'AITaskLog'), + ], + }, + 'System Configuration': { + 'models': [ + ('system', 'AIPrompt'), + ('system', 'Strategy'), ('system', 'AuthorProfile'), - ('system', 'SystemSettings'), - ('system', 'AccountSettings'), - ('system', 'UserSettings'), - ('system', 'ModuleSettings'), - ('system', 'AISettings'), - ('system', 'ModuleEnableSettings'), - ('system', 'SystemLog'), - ('system', 'SystemStatus'), + ('system', 'ContentTemplate'), + ('system', 'TaxonomyConfig'), + ('system', 'SystemSetting'), + ('system', 'ContentTypeConfig'), + ('system', 'PublishingChannel'), + ('system', 'APIKey'), + ('system', 'WebhookConfig'), + ('system', 'NotificationConfig'), + ('system', 'AuditLog'), ], }, - '� Monitoring & Tasks': { + 'Celery Results': { 'models': [ ('django_celery_results', 'TaskResult'), ('django_celery_results', 'GroupResult'), ], }, - '�🔧 Django System': { + 'Content Types': { + 'models': [ + ('contenttypes', 'ContentType'), + ], + }, + 'Administration': { 'models': [ ('admin', 'LogEntry'), + ], + }, + 'Authentication and Authorization': { + 'models': [ ('auth', 'Group'), ('auth', 'Permission'), - ('contenttypes', 'ContentType'), + ], + }, + 'Sessions': { + 'models': [ ('sessions', 'Session'), ], }, } - # Build the custom app list - app_list = [] + # Build the organized app list + 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 - 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 + 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 - # Only add the group if it has models if group_models: - app_list.append({ + organized_apps.append({ 'name': group_name, - 'app_label': group_name.lower().replace(' ', '_').replace('&', '').replace('emoji', ''), - 'app_url': None, + 'app_label': group_name.lower().replace(' ', '_').replace('&', 'and'), + 'app_url': '#', '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 - + return organized_apps +# Create admin site instance +admin_site = Igny8AdminSite(name='admin') diff --git a/backend/igny8_core/admin/site_old.py b/backend/igny8_core/admin/site_old.py new file mode 100644 index 00000000..713d8e7f --- /dev/null +++ b/backend/igny8_core/admin/site_old.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 + + +