from django.contrib import admin from igny8_core.admin.base import SiteSectorAdminMixin from .models import Tasks, Images, Content from igny8_core.business.content.models import ContentTaxonomy, ContentAttribute, ContentTaxonomyRelation class ContentTaxonomyInline(admin.TabularInline): """Inline admin for managing content taxonomy relationships""" model = ContentTaxonomyRelation extra = 1 autocomplete_fields = ['taxonomy'] verbose_name = 'Taxonomy Term' verbose_name_plural = 'Taxonomy Terms (Tags & Categories)' @admin.register(Tasks) class TasksAdmin(SiteSectorAdminMixin, admin.ModelAdmin): list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'status', 'cluster', 'created_at'] list_filter = ['status', 'content_type', 'content_structure', 'site', 'sector', 'cluster'] search_fields = ['title', 'description'] ordering = ['-created_at'] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( ('Basic Info', { 'fields': ('title', 'description', 'status', 'site', 'sector') }), ('Content Classification', { 'fields': ('content_type', 'content_structure', 'taxonomy_term') }), ('Planning', { 'fields': ('cluster', 'keywords') }), ('Timestamps', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def get_site_display(self, obj): """Safely get site name""" try: return obj.site.name if obj.site else '-' except: return '-' get_site_display.short_description = 'Site' def get_sector_display(self, obj): """Safely get sector name""" try: return obj.sector.name if obj.sector else '-' except: return '-' def get_cluster_display(self, obj): """Safely get cluster name""" try: return obj.cluster.name if obj.cluster else '-' except: return '-' get_cluster_display.short_description = 'Cluster' @admin.register(Images) class ImagesAdmin(SiteSectorAdminMixin, admin.ModelAdmin): list_display = ['get_content_title', 'site', 'sector', 'image_type', 'status', 'position', 'created_at'] list_filter = ['image_type', 'status', 'site', 'sector'] search_fields = ['content__title'] ordering = ['-id'] # Sort by ID descending (newest first) def get_content_title(self, obj): """Get content title, fallback to task title if no content""" if obj.content: return obj.content.title or obj.content.meta_title or f"Content #{obj.content.id}" elif obj.task: return obj.task.title or f"Task #{obj.task.id}" return '-' get_content_title.short_description = 'Content Title' def get_site_display(self, obj): """Safely get site name""" try: return obj.site.name if obj.site else '-' except: return '-' get_site_display.short_description = 'Site' def get_sector_display(self, obj): """Safely get sector name""" try: return obj.sector.name if obj.sector else '-' except: return '-' @admin.register(Content) class ContentAdmin(SiteSectorAdminMixin, admin.ModelAdmin): list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'source', 'status', 'get_taxonomy_count', 'created_at'] list_filter = ['content_type', 'content_structure', 'source', 'status', 'site', 'sector', 'created_at'] search_fields = ['title', 'content_html', 'external_url'] ordering = ['-created_at'] readonly_fields = ['created_at', 'updated_at', 'word_count', 'get_tags_display', 'get_categories_display'] inlines = [ContentTaxonomyInline] fieldsets = ( ('Basic Info', { 'fields': ('title', 'site', 'sector', 'cluster', 'status') }), ('Content Classification', { 'fields': ('content_type', 'content_structure', 'source') }), ('Taxonomies (Read-only - manage below)', { 'fields': ('get_tags_display', 'get_categories_display'), 'classes': ('collapse',), 'description': 'View tags and categories. To add/remove, use the Taxonomy Terms section below.' }), ('Content', { 'fields': ('content_html', 'word_count') }), ('SEO', { 'fields': ('meta_title', 'meta_description', 'primary_keyword', 'secondary_keywords'), 'classes': ('collapse',) }), ('WordPress Sync', { 'fields': ('external_id', 'external_url'), 'classes': ('collapse',) }), ('Timestamps', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def get_taxonomy_count(self, obj): """Display count of associated taxonomy terms""" return obj.taxonomy_terms.count() get_taxonomy_count.short_description = 'Taxonomy Count' def get_tags_display(self, obj): """Display tags""" tags = obj.taxonomy_terms.filter(taxonomy_type='tag') if tags.exists(): return ', '.join([tag.name for tag in tags]) return 'No tags' get_tags_display.short_description = 'Tags' def get_categories_display(self, obj): """Display categories""" categories = obj.taxonomy_terms.filter(taxonomy_type='category') if categories.exists(): return ', '.join([cat.name for cat in categories]) return 'No categories' get_categories_display.short_description = 'Categories' def get_site_display(self, obj): """Safely get site name""" try: return obj.site.name if obj.site else '-' except: return '-' get_site_display.short_description = 'Site' def get_sector_display(self, obj): """Safely get sector name""" try: return obj.sector.name if obj.sector else '-' except: return '-' @admin.register(ContentTaxonomy) class ContentTaxonomyAdmin(SiteSectorAdminMixin, admin.ModelAdmin): list_display = ['name', 'taxonomy_type', 'slug', 'count', 'external_id', 'external_taxonomy', 'site', 'sector'] list_filter = ['taxonomy_type', 'site', 'sector'] search_fields = ['name', 'slug', 'external_taxonomy'] ordering = ['taxonomy_type', 'name'] readonly_fields = ['count', 'created_at', 'updated_at'] fieldsets = ( ('Basic Info', { 'fields': ('name', 'slug', 'taxonomy_type', 'description', 'site', 'sector') }), ('Usage', { 'fields': ('count',), 'description': 'Number of content items using this term' }), ('WordPress Sync', { 'fields': ('external_id', 'external_taxonomy', 'metadata'), 'classes': ('collapse',) }), ('Timestamps', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('site', 'sector') @admin.register(ContentAttribute) class ContentAttributeAdmin(SiteSectorAdminMixin, admin.ModelAdmin): list_display = ['name', 'value', 'attribute_type', 'content', 'cluster', 'external_id', 'source', 'site', 'sector'] list_filter = ['attribute_type', 'source', 'site', 'sector'] search_fields = ['name', 'value', 'external_attribute_name', 'content__title'] ordering = ['attribute_type', 'name'] fieldsets = ( ('Basic Info', { 'fields': ('attribute_type', 'name', 'value', 'site', 'sector') }), ('Relationships', { 'fields': ('content', 'cluster'), 'description': 'Link to content (products/services) or cluster (semantic attributes).' }), ('WordPress/WooCommerce Sync', { 'fields': ('external_id', 'external_attribute_name', 'source', 'metadata') }), ) def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related('content', 'cluster', 'site', 'sector')