sadasda
This commit is contained in:
@@ -89,8 +89,9 @@ class CeleryTaskResultAdmin(ModelAdmin):
|
||||
execution_time.short_description = 'Duration'
|
||||
|
||||
def retry_failed_tasks(self, request, queryset):
|
||||
"""Retry failed celery tasks"""
|
||||
from celery import current_app
|
||||
"""Retry failed celery tasks by re-queuing them"""
|
||||
from igny8_core.celery import app
|
||||
import json
|
||||
|
||||
failed_tasks = queryset.filter(status='FAILURE')
|
||||
count = 0
|
||||
@@ -119,13 +120,13 @@ class CeleryTaskResultAdmin(ModelAdmin):
|
||||
errors.append(f'Error retrying {task.task_id}: {str(e)}')
|
||||
|
||||
if count > 0:
|
||||
self.message_user(request, f'✅ Retried {count} failed task(s)', messages.SUCCESS)
|
||||
self.message_user(request, f'Successfully queued {count} task(s) for retry.', 'SUCCESS')
|
||||
|
||||
if errors:
|
||||
for error in errors[:5]: # Show max 5 errors
|
||||
self.message_user(request, f'⚠️ {error}', messages.WARNING)
|
||||
self.message_user(request, f'Error: {error}', 'WARNING')
|
||||
|
||||
retry_failed_tasks.short_description = '🔄 Retry Failed Tasks'
|
||||
retry_failed_tasks.short_description = 'Retry Failed Tasks'
|
||||
|
||||
def clear_old_tasks(self, request, queryset):
|
||||
"""Clear old completed tasks"""
|
||||
|
||||
@@ -18,13 +18,21 @@ def admin_dashboard(request):
|
||||
month_ago = today - timedelta(days=30)
|
||||
|
||||
# Account metrics
|
||||
from igny8_core.auth.models import Account
|
||||
from igny8_core.auth.models import Account, Site
|
||||
total_accounts = Account.objects.count()
|
||||
active_accounts = Account.objects.filter(status='active').count()
|
||||
low_credit_accounts = Account.objects.filter(
|
||||
status='active',
|
||||
credits__lt=100
|
||||
).count()
|
||||
critical_credit_accounts = Account.objects.filter(
|
||||
status='active',
|
||||
credits__lt=10
|
||||
).count()
|
||||
|
||||
# Site metrics
|
||||
total_sites = Site.objects.count()
|
||||
active_sites = Site.objects.filter(is_active=True, status='active').count()
|
||||
|
||||
# Content metrics
|
||||
from igny8_core.modules.writer.models import Content, Tasks
|
||||
@@ -54,58 +62,123 @@ def admin_dashboard(request):
|
||||
started_at__gte=week_ago
|
||||
).count()
|
||||
|
||||
# Calculate success rate
|
||||
total_runs = AutomationRun.objects.filter(started_at__gte=week_ago).count()
|
||||
if total_runs > 0:
|
||||
success_runs = AutomationRun.objects.filter(
|
||||
started_at__gte=week_ago,
|
||||
status='completed'
|
||||
).count()
|
||||
automation_success_rate = round((success_runs / total_runs) * 100, 1)
|
||||
else:
|
||||
automation_success_rate = 0
|
||||
|
||||
# WordPress sync metrics
|
||||
from igny8_core.business.integration.models import SyncEvent
|
||||
sync_failed_today = SyncEvent.objects.filter(
|
||||
success=False,
|
||||
created_at__date=today
|
||||
).count()
|
||||
sync_success_today = SyncEvent.objects.filter(
|
||||
success=True,
|
||||
created_at__date=today
|
||||
).count()
|
||||
|
||||
# Celery task metrics
|
||||
try:
|
||||
from django_celery_results.models import TaskResult
|
||||
celery_failed = TaskResult.objects.filter(
|
||||
status='FAILURE',
|
||||
date_created__date=today
|
||||
date_created__gte=week_ago
|
||||
).count()
|
||||
celery_pending = TaskResult.objects.filter(status='PENDING').count()
|
||||
except:
|
||||
celery_failed = 0
|
||||
celery_pending = 0
|
||||
|
||||
# Get alerts
|
||||
from .alerts import AdminAlerts
|
||||
alerts = AdminAlerts.get_alerts()
|
||||
# Generate alerts
|
||||
alerts = []
|
||||
|
||||
if critical_credit_accounts > 0:
|
||||
alerts.append({
|
||||
'level': 'error',
|
||||
'message': f'{critical_credit_accounts} account(s) have CRITICAL low credits (< 10)',
|
||||
'action': 'Review Accounts',
|
||||
'url': '/admin/igny8_core_auth/account/?credits__lt=10'
|
||||
})
|
||||
|
||||
if low_credit_accounts > 0:
|
||||
alerts.append({
|
||||
'level': 'warning',
|
||||
'message': f'{low_credit_accounts} account(s) have low credits (< 100)',
|
||||
'action': 'Review Accounts',
|
||||
'url': '/admin/igny8_core_auth/account/?credits__lt=100'
|
||||
})
|
||||
|
||||
if pending_payments > 0:
|
||||
alerts.append({
|
||||
'level': 'warning',
|
||||
'message': f'{pending_payments} payment(s) awaiting approval',
|
||||
'action': 'Approve Payments',
|
||||
'url': '/admin/billing/payment/?status__exact=pending_approval'
|
||||
})
|
||||
|
||||
if automation_failed > 5:
|
||||
alerts.append({
|
||||
'level': 'error',
|
||||
'message': f'{automation_failed} automation runs failed this week',
|
||||
'action': 'View Failed Runs',
|
||||
'url': '/admin/automation/automationrun/?status__exact=failed'
|
||||
})
|
||||
|
||||
if sync_failed_today > 0:
|
||||
alerts.append({
|
||||
'level': 'warning',
|
||||
'message': f'{sync_failed_today} WordPress sync failure(s) today',
|
||||
'action': 'View Sync Events',
|
||||
'url': '/admin/integration/syncevent/?success__exact=0'
|
||||
})
|
||||
|
||||
if celery_failed > 10:
|
||||
alerts.append({
|
||||
'level': 'error',
|
||||
'message': f'{celery_failed} Celery tasks failed this week',
|
||||
'action': 'View Failed Tasks',
|
||||
'url': '/admin/django_celery_results/taskresult/?status__exact=FAILURE'
|
||||
})
|
||||
|
||||
context = {
|
||||
'title': 'IGNY8 Dashboard',
|
||||
'accounts': {
|
||||
'total': total_accounts,
|
||||
'active': active_accounts,
|
||||
'low_credit': low_credit_accounts,
|
||||
},
|
||||
'content': {
|
||||
'this_week': content_this_week,
|
||||
'this_month': content_this_month,
|
||||
'tasks_pending': tasks_pending,
|
||||
'tasks_in_progress': tasks_in_progress,
|
||||
},
|
||||
'billing': {
|
||||
'pending_payments': pending_payments,
|
||||
'payments_this_month': float(payments_this_month),
|
||||
'credit_usage_this_month': abs(credit_usage_this_month),
|
||||
},
|
||||
'automation': {
|
||||
'running': automation_running,
|
||||
'failed_this_week': automation_failed,
|
||||
},
|
||||
'integration': {
|
||||
'sync_failed_today': sync_failed_today,
|
||||
},
|
||||
'celery': {
|
||||
'failed_today': celery_failed,
|
||||
'pending': celery_pending,
|
||||
},
|
||||
'site_title': 'IGNY8 Admin',
|
||||
'site_header': 'IGNY8 Administration',
|
||||
# Account metrics
|
||||
'total_accounts': total_accounts,
|
||||
'active_accounts': active_accounts,
|
||||
'low_credit_accounts': low_credit_accounts,
|
||||
'critical_credit_accounts': critical_credit_accounts,
|
||||
# Site metrics
|
||||
'total_sites': total_sites,
|
||||
'active_sites': active_sites,
|
||||
# Content metrics
|
||||
'content_this_week': content_this_week,
|
||||
'content_this_month': content_this_month,
|
||||
'tasks_pending': tasks_pending,
|
||||
'tasks_in_progress': tasks_in_progress,
|
||||
# Billing metrics
|
||||
'pending_payments': pending_payments,
|
||||
'payments_this_month': float(payments_this_month),
|
||||
'credit_usage_this_month': abs(float(credit_usage_this_month)),
|
||||
# Automation metrics
|
||||
'automation_running': automation_running,
|
||||
'automation_failed': automation_failed,
|
||||
'automation_success_rate': automation_success_rate,
|
||||
# Integration metrics
|
||||
'sync_failed_today': sync_failed_today,
|
||||
'sync_success_today': sync_success_today,
|
||||
# Celery metrics
|
||||
'celery_failed': celery_failed,
|
||||
'celery_pending': celery_pending,
|
||||
# Alerts
|
||||
'alerts': alerts,
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,29 @@ class Igny8AdminSite(UnfoldAdminSite):
|
||||
index_title = 'IGNY8 Administration'
|
||||
|
||||
def get_urls(self):
|
||||
"""Get admin URLs without custom dashboard"""
|
||||
"""Get admin URLs - dashboard available at /admin/dashboard/ but not default"""
|
||||
urls = super().get_urls()
|
||||
# Dashboard is available at /admin/dashboard/ if needed, but not redirecting by default
|
||||
# from django.urls import path
|
||||
# from .dashboard import admin_dashboard
|
||||
# custom_urls = [
|
||||
# path('dashboard/', self.admin_view(admin_dashboard), name='dashboard'),
|
||||
# ]
|
||||
# return custom_urls + 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
|
||||
|
||||
CRITICAL FIX: Force custom sidebar on ALL pages including model detail/list views
|
||||
"""
|
||||
context = super().each_context(request)
|
||||
# Force our custom app list to be used everywhere
|
||||
context['available_apps'] = self.get_app_list(request)
|
||||
# Force our custom app list to be used everywhere - IGNORE app_label parameter
|
||||
custom_apps = self.get_app_list(request, app_label=None)
|
||||
context['available_apps'] = custom_apps
|
||||
context['app_list'] = custom_apps # Also set app_list for compatibility
|
||||
return context
|
||||
|
||||
def get_app_list(self, request, app_label=None):
|
||||
@@ -42,10 +53,10 @@ class Igny8AdminSite(UnfoldAdminSite):
|
||||
|
||||
Args:
|
||||
request: The HTTP request
|
||||
app_label: Optional app label to filter (used for app index pages)
|
||||
app_label: IGNORED - Always return full custom sidebar for consistency
|
||||
"""
|
||||
# Get the default app list
|
||||
app_dict = self._build_app_dict(request, app_label)
|
||||
# CRITICAL: Always build full app_dict (ignore app_label) for consistent sidebar
|
||||
app_dict = self._build_app_dict(request, None)
|
||||
|
||||
# Define our custom groups with their models (using object_name)
|
||||
# Organized by business function - Material icons configured in Unfold
|
||||
|
||||
Reference in New Issue
Block a user