283 lines
8.8 KiB
Python
283 lines
8.8 KiB
Python
from django.contrib import admin
|
|
from django.utils.html import format_html
|
|
from django.urls import reverse
|
|
from django.utils.safestring import mark_safe
|
|
from .models import ContactSubmission
|
|
|
|
|
|
@admin.register(ContactSubmission)
|
|
class ContactSubmissionAdmin(admin.ModelAdmin):
|
|
"""
|
|
Admin interface for ContactSubmission model.
|
|
Provides comprehensive management of contact form submissions.
|
|
"""
|
|
|
|
list_display = [
|
|
'id',
|
|
'full_name_display',
|
|
'company',
|
|
'email',
|
|
'project_type_display',
|
|
'status_badge',
|
|
'priority_badge',
|
|
'is_enterprise_client_display',
|
|
'created_at',
|
|
'assigned_to',
|
|
]
|
|
|
|
list_filter = [
|
|
'status',
|
|
'priority',
|
|
'industry',
|
|
'company_size',
|
|
'project_type',
|
|
'timeline',
|
|
'budget',
|
|
'newsletter_subscription',
|
|
'privacy_consent',
|
|
'created_at',
|
|
'assigned_to',
|
|
]
|
|
|
|
search_fields = [
|
|
'first_name',
|
|
'last_name',
|
|
'email',
|
|
'company',
|
|
'job_title',
|
|
'message',
|
|
]
|
|
|
|
readonly_fields = [
|
|
'id',
|
|
'created_at',
|
|
'updated_at',
|
|
'full_name_display',
|
|
'is_enterprise_client_display',
|
|
'is_high_priority_display',
|
|
]
|
|
|
|
fieldsets = (
|
|
('Personal Information', {
|
|
'fields': (
|
|
'id',
|
|
'first_name',
|
|
'last_name',
|
|
'full_name_display',
|
|
'email',
|
|
'phone',
|
|
)
|
|
}),
|
|
('Company Information', {
|
|
'fields': (
|
|
'company',
|
|
'job_title',
|
|
'industry',
|
|
'company_size',
|
|
'is_enterprise_client_display',
|
|
)
|
|
}),
|
|
('Project Details', {
|
|
'fields': (
|
|
'project_type',
|
|
'timeline',
|
|
'budget',
|
|
'message',
|
|
)
|
|
}),
|
|
('Communication Preferences', {
|
|
'fields': (
|
|
'newsletter_subscription',
|
|
'privacy_consent',
|
|
)
|
|
}),
|
|
('Management', {
|
|
'fields': (
|
|
'status',
|
|
'priority',
|
|
'is_high_priority_display',
|
|
'assigned_to',
|
|
'admin_notes',
|
|
)
|
|
}),
|
|
('Timestamps', {
|
|
'fields': (
|
|
'created_at',
|
|
'updated_at',
|
|
),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
ordering = ['-created_at']
|
|
list_per_page = 25
|
|
date_hierarchy = 'created_at'
|
|
|
|
actions = [
|
|
'mark_as_contacted',
|
|
'mark_as_qualified',
|
|
'mark_as_closed',
|
|
'set_high_priority',
|
|
'set_medium_priority',
|
|
'set_low_priority',
|
|
]
|
|
|
|
def full_name_display(self, obj):
|
|
"""Display full name with link to detail view."""
|
|
return format_html(
|
|
'<strong>{}</strong>',
|
|
obj.full_name
|
|
)
|
|
full_name_display.short_description = 'Full Name'
|
|
full_name_display.admin_order_field = 'first_name'
|
|
|
|
def project_type_display(self, obj):
|
|
"""Display project type with color coding."""
|
|
if not obj.project_type:
|
|
return '-'
|
|
|
|
colors = {
|
|
'software-development': '#007bff',
|
|
'cloud-migration': '#28a745',
|
|
'digital-transformation': '#ffc107',
|
|
'data-analytics': '#17a2b8',
|
|
'security-compliance': '#dc3545',
|
|
'integration': '#6f42c1',
|
|
'consulting': '#fd7e14',
|
|
}
|
|
|
|
color = colors.get(obj.project_type, '#6c757d')
|
|
return format_html(
|
|
'<span style="color: {}; font-weight: bold;">{}</span>',
|
|
color,
|
|
obj.get_project_type_display()
|
|
)
|
|
project_type_display.short_description = 'Project Type'
|
|
project_type_display.admin_order_field = 'project_type'
|
|
|
|
def status_badge(self, obj):
|
|
"""Display status as a colored badge."""
|
|
colors = {
|
|
'new': '#007bff',
|
|
'in_progress': '#ffc107',
|
|
'contacted': '#17a2b8',
|
|
'qualified': '#28a745',
|
|
'closed': '#6c757d',
|
|
}
|
|
|
|
color = colors.get(obj.status, '#6c757d')
|
|
return format_html(
|
|
'<span style="background-color: {}; color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: bold;">{}</span>',
|
|
color,
|
|
obj.get_status_display().upper()
|
|
)
|
|
status_badge.short_description = 'Status'
|
|
status_badge.admin_order_field = 'status'
|
|
|
|
def priority_badge(self, obj):
|
|
"""Display priority as a colored badge."""
|
|
colors = {
|
|
'urgent': '#dc3545',
|
|
'high': '#fd7e14',
|
|
'medium': '#ffc107',
|
|
'low': '#28a745',
|
|
}
|
|
|
|
color = colors.get(obj.priority, '#6c757d')
|
|
return format_html(
|
|
'<span style="background-color: {}; color: white; padding: 2px 8px; border-radius: 12px; font-size: 11px; font-weight: bold;">{}</span>',
|
|
color,
|
|
obj.get_priority_display().upper()
|
|
)
|
|
priority_badge.short_description = 'Priority'
|
|
priority_badge.admin_order_field = 'priority'
|
|
|
|
def is_enterprise_client_display(self, obj):
|
|
"""Display enterprise client status."""
|
|
if obj.is_enterprise_client:
|
|
return format_html(
|
|
'<span style="color: #28a745; font-weight: bold;">✓ Enterprise</span>'
|
|
)
|
|
return format_html(
|
|
'<span style="color: #6c757d;">SMB</span>'
|
|
)
|
|
is_enterprise_client_display.short_description = 'Client Type'
|
|
is_enterprise_client_display.admin_order_field = 'company_size'
|
|
|
|
def is_high_priority_display(self, obj):
|
|
"""Display high priority status."""
|
|
if obj.is_high_priority:
|
|
return format_html(
|
|
'<span style="color: #dc3545; font-weight: bold;">⚠ High Priority</span>'
|
|
)
|
|
return format_html(
|
|
'<span style="color: #6c757d;">Normal</span>'
|
|
)
|
|
is_high_priority_display.short_description = 'Priority Level'
|
|
|
|
# Admin Actions
|
|
def mark_as_contacted(self, request, queryset):
|
|
"""Mark selected submissions as contacted."""
|
|
updated = queryset.update(status='contacted')
|
|
self.message_user(
|
|
request,
|
|
f'{updated} submission(s) marked as contacted.'
|
|
)
|
|
mark_as_contacted.short_description = "Mark selected submissions as contacted"
|
|
|
|
def mark_as_qualified(self, request, queryset):
|
|
"""Mark selected submissions as qualified."""
|
|
updated = queryset.update(status='qualified')
|
|
self.message_user(
|
|
request,
|
|
f'{updated} submission(s) marked as qualified.'
|
|
)
|
|
mark_as_qualified.short_description = "Mark selected submissions as qualified"
|
|
|
|
def mark_as_closed(self, request, queryset):
|
|
"""Mark selected submissions as closed."""
|
|
updated = queryset.update(status='closed')
|
|
self.message_user(
|
|
request,
|
|
f'{updated} submission(s) marked as closed.'
|
|
)
|
|
mark_as_closed.short_description = "Mark selected submissions as closed"
|
|
|
|
def set_high_priority(self, request, queryset):
|
|
"""Set selected submissions to high priority."""
|
|
updated = queryset.update(priority='high')
|
|
self.message_user(
|
|
request,
|
|
f'{updated} submission(s) set to high priority.'
|
|
)
|
|
set_high_priority.short_description = "Set selected submissions to high priority"
|
|
|
|
def set_medium_priority(self, request, queryset):
|
|
"""Set selected submissions to medium priority."""
|
|
updated = queryset.update(priority='medium')
|
|
self.message_user(
|
|
request,
|
|
f'{updated} submission(s) set to medium priority.'
|
|
)
|
|
set_medium_priority.short_description = "Set selected submissions to medium priority"
|
|
|
|
def set_low_priority(self, request, queryset):
|
|
"""Set selected submissions to low priority."""
|
|
updated = queryset.update(priority='low')
|
|
self.message_user(
|
|
request,
|
|
f'{updated} submission(s) set to low priority.'
|
|
)
|
|
set_low_priority.short_description = "Set selected submissions to low priority"
|
|
|
|
def get_queryset(self, request):
|
|
"""Optimize queryset for admin list view."""
|
|
return super().get_queryset(request).select_related()
|
|
|
|
def has_add_permission(self, request):
|
|
"""Disable adding new submissions through admin."""
|
|
return False
|
|
|
|
def has_delete_permission(self, request, obj=None):
|
|
"""Allow deletion only for superusers."""
|
|
return request.user.is_superuser |