Implement Stage 3: Enhance content metadata and validation features

- Added entity metadata fields to the Tasks model, including entity_type, taxonomy, and cluster_role.
- Updated CandidateEngine to prioritize content relevance based on cluster mappings.
- Introduced metadata completeness scoring in ContentAnalyzer.
- Enhanced validation services to check for entity type and mapping completeness.
- Updated frontend components to display and validate new metadata fields.
- Implemented API endpoints for content validation and metadata persistence.
- Migrated existing data to populate new metadata fields for Tasks and Content.
This commit is contained in:
IGNY8 VPS (Salman)
2025-11-19 19:21:30 +00:00
parent 38f6026e73
commit bae9ea47d8
33 changed files with 2388 additions and 73 deletions

View File

@@ -218,6 +218,91 @@ class SiteBlueprintViewSet(SiteSectorModelViewSet):
except Exception as e:
return error_response(str(e), status.HTTP_400_BAD_REQUEST, request)
@action(detail=True, methods=['get'], url_path='progress', url_name='progress')
def progress(self, request, pk=None):
"""
Stage 3: Get cluster-level completion + validation status for site.
GET /api/v1/site-builder/blueprints/{id}/progress/
Returns progress summary with cluster coverage, validation flags.
"""
blueprint = self.get_object()
from igny8_core.business.content.models import (
Tasks,
Content,
ContentClusterMap,
ContentTaxonomyMap,
)
from igny8_core.business.planning.models import Clusters
from django.db.models import Count, Q
# Get clusters attached to blueprint
blueprint_clusters = blueprint.cluster_links.all()
cluster_ids = list(blueprint_clusters.values_list('cluster_id', flat=True))
# Get tasks and content for this blueprint's site
tasks = Tasks.objects.filter(site=blueprint.site)
content = Content.objects.filter(site=blueprint.site)
# Cluster coverage analysis
cluster_progress = []
for cluster_link in blueprint_clusters:
cluster = cluster_link.cluster
cluster_tasks = tasks.filter(cluster=cluster)
cluster_content_ids = ContentClusterMap.objects.filter(
cluster=cluster
).values_list('content_id', flat=True).distinct()
cluster_content = content.filter(id__in=cluster_content_ids)
# Count by role
hub_count = cluster_tasks.filter(cluster_role='hub').count()
supporting_count = cluster_tasks.filter(cluster_role='supporting').count()
attribute_count = cluster_tasks.filter(cluster_role='attribute').count()
cluster_progress.append({
'cluster_id': cluster.id,
'cluster_name': cluster.name,
'role': cluster_link.role,
'coverage_status': cluster_link.coverage_status,
'tasks_count': cluster_tasks.count(),
'content_count': cluster_content.count(),
'hub_pages': hub_count,
'supporting_pages': supporting_count,
'attribute_pages': attribute_count,
'is_complete': cluster_link.coverage_status == 'complete',
})
# Overall stats
total_tasks = tasks.count()
total_content = content.count()
tasks_with_cluster = tasks.filter(cluster__isnull=False).count()
content_with_cluster_map = ContentClusterMap.objects.filter(
content__site=blueprint.site
).values('content').distinct().count()
return success_response(
data={
'blueprint_id': blueprint.id,
'blueprint_name': blueprint.name,
'overall_progress': {
'total_tasks': total_tasks,
'total_content': total_content,
'tasks_with_cluster': tasks_with_cluster,
'content_with_cluster_mapping': content_with_cluster_map,
'completion_percentage': (
(content_with_cluster_map / total_content * 100) if total_content > 0 else 0
),
},
'cluster_progress': cluster_progress,
'validation_flags': {
'has_clusters': blueprint_clusters.exists(),
'has_taxonomies': blueprint.taxonomies.exists(),
'has_pages': blueprint.pages.exists(),
}
},
request=request
)
@action(detail=True, methods=['get'], url_path='workflow/context')
def workflow_context(self, request, pk=None):
"""Return aggregated wizard context (steps, clusters, taxonomies, coverage)."""