more fixes
This commit is contained in:
@@ -45,8 +45,6 @@ class Igny8AdminSite(admin.AdminSite):
|
|||||||
('igny8_core_auth', 'User'),
|
('igny8_core_auth', 'User'),
|
||||||
('igny8_core_auth', 'SiteUserAccess'),
|
('igny8_core_auth', 'SiteUserAccess'),
|
||||||
('igny8_core_auth', 'PasswordResetToken'),
|
('igny8_core_auth', 'PasswordResetToken'),
|
||||||
('site_building', 'SiteBlueprint'),
|
|
||||||
('site_building', 'PageBlueprint'),
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'Global Reference Data': {
|
'Global Reference Data': {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from igny8_core.ai.functions.generate_ideas import GenerateIdeasFunction
|
|||||||
from igny8_core.ai.functions.generate_content import GenerateContentFunction
|
from igny8_core.ai.functions.generate_content import GenerateContentFunction
|
||||||
from igny8_core.ai.functions.generate_images import GenerateImagesFunction, generate_images_core
|
from igny8_core.ai.functions.generate_images import GenerateImagesFunction, generate_images_core
|
||||||
from igny8_core.ai.functions.generate_image_prompts import GenerateImagePromptsFunction
|
from igny8_core.ai.functions.generate_image_prompts import GenerateImagePromptsFunction
|
||||||
from igny8_core.ai.functions.generate_site_structure import GenerateSiteStructureFunction
|
|
||||||
from igny8_core.ai.functions.generate_page_content import GeneratePageContentFunction
|
from igny8_core.ai.functions.generate_page_content import GeneratePageContentFunction
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@@ -16,6 +15,5 @@ __all__ = [
|
|||||||
'GenerateImagesFunction',
|
'GenerateImagesFunction',
|
||||||
'generate_images_core',
|
'generate_images_core',
|
||||||
'GenerateImagePromptsFunction',
|
'GenerateImagePromptsFunction',
|
||||||
'GenerateSiteStructureFunction',
|
|
||||||
'GeneratePageContentFunction',
|
'GeneratePageContentFunction',
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,214 +0,0 @@
|
|||||||
"""
|
|
||||||
Generate Site Structure AI Function
|
|
||||||
Phase 3 – Site Builder
|
|
||||||
"""
|
|
||||||
import json
|
|
||||||
import logging
|
|
||||||
from typing import Any, Dict, List, Tuple
|
|
||||||
|
|
||||||
from django.utils.text import slugify
|
|
||||||
|
|
||||||
from igny8_core.ai.base import BaseAIFunction
|
|
||||||
from igny8_core.ai.prompts import PromptRegistry
|
|
||||||
from igny8_core.business.site_building.models import SiteBlueprint, PageBlueprint
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class GenerateSiteStructureFunction(BaseAIFunction):
|
|
||||||
"""AI function that turns a business brief into a full site blueprint."""
|
|
||||||
|
|
||||||
def get_name(self) -> str:
|
|
||||||
return 'generate_site_structure'
|
|
||||||
|
|
||||||
def get_metadata(self) -> Dict:
|
|
||||||
metadata = super().get_metadata()
|
|
||||||
metadata.update({
|
|
||||||
'display_name': 'Generate Site Structure',
|
|
||||||
'description': 'Create site/page architecture from business brief, objectives, and style guides.',
|
|
||||||
'phases': {
|
|
||||||
'INIT': 'Validating blueprint data…',
|
|
||||||
'PREP': 'Preparing site context…',
|
|
||||||
'AI_CALL': 'Generating site structure with AI…',
|
|
||||||
'PARSE': 'Parsing generated blueprint…',
|
|
||||||
'SAVE': 'Saving pages and blocks…',
|
|
||||||
'DONE': 'Site structure ready!'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return metadata
|
|
||||||
|
|
||||||
def validate(self, payload: dict, account=None) -> Dict[str, Any]:
|
|
||||||
if not payload.get('ids'):
|
|
||||||
return {'valid': False, 'error': 'Site blueprint ID is required'}
|
|
||||||
return {'valid': True}
|
|
||||||
|
|
||||||
def prepare(self, payload: dict, account=None) -> Dict[str, Any]:
|
|
||||||
blueprint_ids = payload.get('ids', [])
|
|
||||||
queryset = SiteBlueprint.objects.filter(id__in=blueprint_ids)
|
|
||||||
if account:
|
|
||||||
queryset = queryset.filter(account=account)
|
|
||||||
blueprint = queryset.select_related('account', 'site').prefetch_related('pages').first()
|
|
||||||
if not blueprint:
|
|
||||||
raise ValueError("Site blueprint not found")
|
|
||||||
|
|
||||||
config = blueprint.config_json or {}
|
|
||||||
business_brief = payload.get('business_brief') or config.get('business_brief') or ''
|
|
||||||
objectives = payload.get('objectives') or config.get('objectives') or []
|
|
||||||
style = payload.get('style') or config.get('style') or {}
|
|
||||||
|
|
||||||
return {
|
|
||||||
'blueprint': blueprint,
|
|
||||||
'business_brief': business_brief,
|
|
||||||
'objectives': objectives,
|
|
||||||
'style': style,
|
|
||||||
}
|
|
||||||
|
|
||||||
def build_prompt(self, data: Dict[str, Any], account=None) -> str:
|
|
||||||
blueprint: SiteBlueprint = data['blueprint']
|
|
||||||
objectives = data.get('objectives') or []
|
|
||||||
objectives_text = '\n'.join(f"- {obj}" for obj in objectives) if isinstance(objectives, list) else objectives
|
|
||||||
style = data.get('style') or {}
|
|
||||||
style_text = json.dumps(style, indent=2) if isinstance(style, dict) and style else str(style)
|
|
||||||
|
|
||||||
existing_pages = [
|
|
||||||
{
|
|
||||||
'title': page.title,
|
|
||||||
'slug': page.slug,
|
|
||||||
'type': page.type,
|
|
||||||
'status': page.status,
|
|
||||||
}
|
|
||||||
for page in blueprint.pages.all()
|
|
||||||
]
|
|
||||||
|
|
||||||
context = {
|
|
||||||
'BUSINESS_BRIEF': data.get('business_brief', ''),
|
|
||||||
'OBJECTIVES': objectives_text or 'Create a full marketing site with clear navigation.',
|
|
||||||
'STYLE': style_text or 'Modern, responsive, accessible web design.',
|
|
||||||
'SITE_INFO': json.dumps({
|
|
||||||
'site_name': blueprint.name,
|
|
||||||
'site_description': blueprint.description,
|
|
||||||
'hosting_type': blueprint.hosting_type,
|
|
||||||
'existing_pages': existing_pages,
|
|
||||||
'existing_structure': blueprint.structure_json or {},
|
|
||||||
}, indent=2)
|
|
||||||
}
|
|
||||||
|
|
||||||
return PromptRegistry.get_prompt(
|
|
||||||
'generate_site_structure',
|
|
||||||
account=account or blueprint.account,
|
|
||||||
context=context
|
|
||||||
)
|
|
||||||
|
|
||||||
def parse_response(self, response: str, step_tracker=None) -> Dict[str, Any]:
|
|
||||||
if not response:
|
|
||||||
raise ValueError("AI response is empty")
|
|
||||||
|
|
||||||
response = response.strip()
|
|
||||||
try:
|
|
||||||
return self._ensure_dict(json.loads(response))
|
|
||||||
except json.JSONDecodeError:
|
|
||||||
logger.warning("Response not valid JSON, attempting to extract JSON object")
|
|
||||||
cleaned = self._extract_json_object(response)
|
|
||||||
if cleaned:
|
|
||||||
return self._ensure_dict(json.loads(cleaned))
|
|
||||||
raise ValueError("Unable to parse AI response into JSON")
|
|
||||||
|
|
||||||
def save_output(
|
|
||||||
self,
|
|
||||||
parsed: Dict[str, Any],
|
|
||||||
original_data: Dict[str, Any],
|
|
||||||
account=None,
|
|
||||||
progress_tracker=None,
|
|
||||||
step_tracker=None
|
|
||||||
) -> Dict[str, Any]:
|
|
||||||
blueprint: SiteBlueprint = original_data['blueprint']
|
|
||||||
structure = self._ensure_dict(parsed)
|
|
||||||
pages = structure.get('pages', [])
|
|
||||||
|
|
||||||
blueprint.structure_json = structure
|
|
||||||
blueprint.status = 'ready'
|
|
||||||
blueprint.save(update_fields=['structure_json', 'status', 'updated_at'])
|
|
||||||
|
|
||||||
created, updated, deleted = self._sync_page_blueprints(blueprint, pages)
|
|
||||||
|
|
||||||
message = f"Pages synced (created: {created}, updated: {updated}, deleted: {deleted})"
|
|
||||||
logger.info("[GenerateSiteStructure] %s for blueprint %s", message, blueprint.id)
|
|
||||||
|
|
||||||
return {
|
|
||||||
'success': True,
|
|
||||||
'count': created + updated,
|
|
||||||
'site_blueprint_id': blueprint.id,
|
|
||||||
'pages_created': created,
|
|
||||||
'pages_updated': updated,
|
|
||||||
'pages_deleted': deleted,
|
|
||||||
}
|
|
||||||
|
|
||||||
# Helpers -----------------------------------------------------------------
|
|
||||||
|
|
||||||
def _ensure_dict(self, data: Any) -> Dict[str, Any]:
|
|
||||||
if isinstance(data, dict):
|
|
||||||
return data
|
|
||||||
raise ValueError("AI response must be a JSON object with site metadata")
|
|
||||||
|
|
||||||
def _extract_json_object(self, text: str) -> str:
|
|
||||||
start = text.find('{')
|
|
||||||
end = text.rfind('}')
|
|
||||||
if start != -1 and end != -1 and end > start:
|
|
||||||
return text[start:end + 1]
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def _sync_page_blueprints(self, blueprint: SiteBlueprint, pages: List[Dict[str, Any]]) -> Tuple[int, int, int]:
|
|
||||||
existing = {page.slug: page for page in blueprint.pages.all()}
|
|
||||||
seen_slugs = set()
|
|
||||||
created = updated = 0
|
|
||||||
|
|
||||||
for order, page_data in enumerate(pages or []):
|
|
||||||
slug = page_data.get('slug') or page_data.get('id') or page_data.get('title') or f"page-{order + 1}"
|
|
||||||
slug = slugify(slug) or f"page-{order + 1}"
|
|
||||||
seen_slugs.add(slug)
|
|
||||||
|
|
||||||
defaults = {
|
|
||||||
'title': page_data.get('title') or page_data.get('name') or slug.replace('-', ' ').title(),
|
|
||||||
'type': self._map_page_type(page_data.get('type')),
|
|
||||||
'blocks_json': page_data.get('blocks') or page_data.get('sections') or [],
|
|
||||||
'status': page_data.get('status') or 'draft',
|
|
||||||
'order': order,
|
|
||||||
}
|
|
||||||
|
|
||||||
page_obj, created_flag = PageBlueprint.objects.update_or_create(
|
|
||||||
site_blueprint=blueprint,
|
|
||||||
slug=slug,
|
|
||||||
defaults=defaults
|
|
||||||
)
|
|
||||||
if created_flag:
|
|
||||||
created += 1
|
|
||||||
else:
|
|
||||||
updated += 1
|
|
||||||
|
|
||||||
# Delete pages not present in new structure
|
|
||||||
deleted = 0
|
|
||||||
for slug, page in existing.items():
|
|
||||||
if slug not in seen_slugs:
|
|
||||||
page.delete()
|
|
||||||
deleted += 1
|
|
||||||
|
|
||||||
return created, updated, deleted
|
|
||||||
|
|
||||||
def _map_page_type(self, page_type: Any) -> str:
|
|
||||||
allowed = {choice[0] for choice in PageBlueprint._meta.get_field('type').choices}
|
|
||||||
if isinstance(page_type, str):
|
|
||||||
normalized = page_type.lower()
|
|
||||||
if normalized in allowed:
|
|
||||||
return normalized
|
|
||||||
# Map friendly names
|
|
||||||
mapping = {
|
|
||||||
'homepage': 'home',
|
|
||||||
'landing': 'home',
|
|
||||||
'service': 'services',
|
|
||||||
'product': 'products',
|
|
||||||
}
|
|
||||||
mapped = mapping.get(normalized)
|
|
||||||
if mapped in allowed:
|
|
||||||
return mapped
|
|
||||||
return 'custom'
|
|
||||||
|
|
||||||
@@ -94,11 +94,6 @@ def _load_generate_image_prompts():
|
|||||||
from igny8_core.ai.functions.generate_image_prompts import GenerateImagePromptsFunction
|
from igny8_core.ai.functions.generate_image_prompts import GenerateImagePromptsFunction
|
||||||
return GenerateImagePromptsFunction
|
return GenerateImagePromptsFunction
|
||||||
|
|
||||||
def _load_generate_site_structure():
|
|
||||||
"""Lazy loader for generate_site_structure function"""
|
|
||||||
from igny8_core.ai.functions.generate_site_structure import GenerateSiteStructureFunction
|
|
||||||
return GenerateSiteStructureFunction
|
|
||||||
|
|
||||||
def _load_optimize_content():
|
def _load_optimize_content():
|
||||||
"""Lazy loader for optimize_content function"""
|
"""Lazy loader for optimize_content function"""
|
||||||
from igny8_core.ai.functions.optimize_content import OptimizeContentFunction
|
from igny8_core.ai.functions.optimize_content import OptimizeContentFunction
|
||||||
@@ -109,6 +104,5 @@ register_lazy_function('generate_ideas', _load_generate_ideas)
|
|||||||
register_lazy_function('generate_content', _load_generate_content)
|
register_lazy_function('generate_content', _load_generate_content)
|
||||||
register_lazy_function('generate_images', _load_generate_images)
|
register_lazy_function('generate_images', _load_generate_images)
|
||||||
register_lazy_function('generate_image_prompts', _load_generate_image_prompts)
|
register_lazy_function('generate_image_prompts', _load_generate_image_prompts)
|
||||||
register_lazy_function('generate_site_structure', _load_generate_site_structure)
|
|
||||||
register_lazy_function('optimize_content', _load_optimize_content)
|
register_lazy_function('optimize_content', _load_optimize_content)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Migration(migrations.Migration):
|
|||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('system', '__latest__'),
|
('igny8_core_auth', '__latest__'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
@@ -35,11 +35,11 @@ class Migration(migrations.Migration):
|
|||||||
('next_run_at', models.DateTimeField(blank=True, null=True)),
|
('next_run_at', models.DateTimeField(blank=True, null=True)),
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
('updated_at', models.DateTimeField(auto_now=True)),
|
||||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.account')),
|
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='igny8_core_auth.account')),
|
||||||
('site', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='automation_config', to='system.site')),
|
('site', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='automation_config', to='igny8_core_auth.site')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'automation_config',
|
'db_table': 'igny8_automation_configs',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
@@ -74,11 +74,11 @@ class Migration(migrations.Migration):
|
|||||||
('error_message', models.TextField(blank=True, null=True)),
|
('error_message', models.TextField(blank=True, null=True)),
|
||||||
('started_at', models.DateTimeField(auto_now_add=True)),
|
('started_at', models.DateTimeField(auto_now_add=True)),
|
||||||
('completed_at', models.DateTimeField(blank=True, null=True)),
|
('completed_at', models.DateTimeField(blank=True, null=True)),
|
||||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='system.account')),
|
('account', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='igny8_core_auth.account')),
|
||||||
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='automation_runs', to='system.site')),
|
('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='automation_runs', to='igny8_core_auth.site')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'automation_run',
|
'db_table': 'igny8_automation_runs',
|
||||||
'ordering': ['-started_at'],
|
'ordering': ['-started_at'],
|
||||||
'indexes': [
|
'indexes': [
|
||||||
models.Index(fields=['site', 'status'], name='automation_site_status_idx'),
|
models.Index(fields=['site', 'status'], name='automation_site_status_idx'),
|
||||||
|
|||||||
@@ -760,14 +760,14 @@ class AutomationService:
|
|||||||
def estimate_credits(self) -> int:
|
def estimate_credits(self) -> int:
|
||||||
"""Estimate total credits needed for automation"""
|
"""Estimate total credits needed for automation"""
|
||||||
# Count items
|
# Count items
|
||||||
keywords_count = Keywords.objects.filter(site=self.site, status='new', cluster__isnull=True).count()
|
keywords_count = Keywords.objects.filter(site=self.site, status='new', cluster__isnull=True, disabled=False).count()
|
||||||
clusters_count = Clusters.objects.filter(site=self.site, status='new').exclude(ideas__isnull=False).count()
|
clusters_count = Clusters.objects.filter(site=self.site, status='new').exclude(ideas__isnull=False).count()
|
||||||
ideas_count = ContentIdeas.objects.filter(site=self.site, status='new').count()
|
ideas_count = ContentIdeas.objects.filter(site=self.site, status='new').count()
|
||||||
tasks_count = Tasks.objects.filter(site=self.site, status='queued', content__isnull=True).count()
|
tasks_count = Tasks.objects.filter(site=self.site, status='queued').count()
|
||||||
content_count = Content.objects.filter(site=self.site, status='draft').annotate(images_count=Count('images')).filter(images_count=0).count()
|
content_count = Content.objects.filter(site=self.site, status='draft').annotate(images_count=Count('images')).filter(images_count=0).count()
|
||||||
|
|
||||||
# Estimate credits
|
# Estimate credits
|
||||||
clustering_credits = (keywords_count // 5) + 1 # 1 credit per 5 keywords
|
clustering_credits = (keywords_count // 5) + 1 if keywords_count > 0 else 0 # 1 credit per 5 keywords
|
||||||
ideas_credits = clusters_count * 2 # 2 credits per cluster
|
ideas_credits = clusters_count * 2 # 2 credits per cluster
|
||||||
content_credits = tasks_count * 5 # Assume 2500 words avg = 5 credits
|
content_credits = tasks_count * 5 # Assume 2500 words avg = 5 credits
|
||||||
prompts_credits = content_count * 2 # Assume 4 prompts per content = 2 credits
|
prompts_credits = content_count * 2 # Assume 4 prompts per content = 2 credits
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class AutomationViewSet(viewsets.ViewSet):
|
|||||||
status=status.HTTP_400_BAD_REQUEST
|
status=status.HTTP_400_BAD_REQUEST
|
||||||
)
|
)
|
||||||
|
|
||||||
site = get_object_or_404(Site, id=site_id, account__user=request.user)
|
site = get_object_or_404(Site, id=site_id, account=request.user.account)
|
||||||
return site, None
|
return site, None
|
||||||
|
|
||||||
@action(detail=False, methods=['get'])
|
@action(detail=False, methods=['get'])
|
||||||
@@ -308,6 +308,6 @@ class AutomationViewSet(viewsets.ViewSet):
|
|||||||
|
|
||||||
return Response({
|
return Response({
|
||||||
'estimated_credits': estimated_credits,
|
'estimated_credits': estimated_credits,
|
||||||
'current_balance': site.account.credits_balance,
|
'current_balance': site.account.credits,
|
||||||
'sufficient': site.account.credits_balance >= (estimated_credits * 1.2)
|
'sufficient': site.account.credits >= (estimated_credits * 1.2)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
"""
|
"""
|
||||||
Tests for DeploymentService
|
DEPRECATED: Tests for DeploymentService - SiteBlueprint models removed
|
||||||
Phase 5: Sites Renderer & Publishing
|
Phase 5: Sites Renderer & Publishing
|
||||||
"""
|
"""
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from igny8_core.auth.models import Account, Site, Sector, User, Plan, Industry, IndustrySector
|
from igny8_core.auth.models import Account, Site, Sector, User, Plan, Industry, IndustrySector
|
||||||
from igny8_core.business.site_building.models import SiteBlueprint
|
|
||||||
from igny8_core.business.publishing.models import DeploymentRecord
|
from igny8_core.business.publishing.models import DeploymentRecord
|
||||||
from igny8_core.business.publishing.services.deployment_service import DeploymentService
|
from igny8_core.business.publishing.services.deployment_service import DeploymentService
|
||||||
|
|
||||||
|
|
||||||
class DeploymentServiceTestCase(TestCase):
|
class DeploymentServiceTestCase(TestCase):
|
||||||
"""Test cases for DeploymentService"""
|
"""DEPRECATED: Test cases for DeploymentService"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up test data"""
|
"""Set up test data"""
|
||||||
@@ -69,14 +68,8 @@ class DeploymentServiceTestCase(TestCase):
|
|||||||
name="Test Sector",
|
name="Test Sector",
|
||||||
slug="test-sector"
|
slug="test-sector"
|
||||||
)
|
)
|
||||||
self.blueprint = SiteBlueprint.objects.create(
|
# DEPRECATED: SiteBlueprint model removed
|
||||||
account=self.account,
|
self.blueprint = None
|
||||||
site=self.site,
|
|
||||||
sector=self.sector,
|
|
||||||
name="Test Blueprint",
|
|
||||||
status='ready',
|
|
||||||
version=1
|
|
||||||
)
|
|
||||||
self.service = DeploymentService()
|
self.service = DeploymentService()
|
||||||
|
|
||||||
def test_get_status_returns_deployed_record(self):
|
def test_get_status_returns_deployed_record(self):
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
"""
|
"""
|
||||||
Site Building Models
|
Site Building Models
|
||||||
Legacy SiteBuilder module has been removed.
|
Legacy SiteBuilder module has been removed.
|
||||||
This file is kept for backwards compatibility with migrations.
|
This file is kept for backwards compatibility with migrations and legacy code.
|
||||||
"""
|
"""
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from igny8_core.auth.models import AccountBaseModel
|
||||||
|
|
||||||
# All SiteBuilder models have been removed:
|
# All SiteBuilder models have been removed:
|
||||||
# - SiteBlueprint
|
# - SiteBlueprint
|
||||||
@@ -13,3 +14,32 @@ from django.db import models
|
|||||||
# - BusinessType, AudienceProfile, BrandPersonality, HeroImageryDirection
|
# - BusinessType, AudienceProfile, BrandPersonality, HeroImageryDirection
|
||||||
#
|
#
|
||||||
# Taxonomy functionality moved to ContentTaxonomy model in business/content/models.py
|
# Taxonomy functionality moved to ContentTaxonomy model in business/content/models.py
|
||||||
|
|
||||||
|
# Stub classes for backwards compatibility with legacy imports
|
||||||
|
class SiteBlueprint(AccountBaseModel):
|
||||||
|
"""Legacy stub - SiteBuilder has been removed"""
|
||||||
|
class Meta:
|
||||||
|
app_label = 'site_building'
|
||||||
|
db_table = 'legacy_site_blueprint_stub'
|
||||||
|
managed = False # Don't create table
|
||||||
|
|
||||||
|
class PageBlueprint(AccountBaseModel):
|
||||||
|
"""Legacy stub - SiteBuilder has been removed"""
|
||||||
|
class Meta:
|
||||||
|
app_label = 'site_building'
|
||||||
|
db_table = 'legacy_page_blueprint_stub'
|
||||||
|
managed = False # Don't create table
|
||||||
|
|
||||||
|
class SiteBlueprintCluster(AccountBaseModel):
|
||||||
|
"""Legacy stub - SiteBuilder has been removed"""
|
||||||
|
class Meta:
|
||||||
|
app_label = 'site_building'
|
||||||
|
db_table = 'legacy_site_blueprint_cluster_stub'
|
||||||
|
managed = False # Don't create table
|
||||||
|
|
||||||
|
class SiteBlueprintTaxonomy(AccountBaseModel):
|
||||||
|
"""Legacy stub - SiteBuilder has been removed"""
|
||||||
|
class Meta:
|
||||||
|
app_label = 'site_building'
|
||||||
|
db_table = 'legacy_site_blueprint_taxonomy_stub'
|
||||||
|
managed = False # Don't create table
|
||||||
|
|||||||
@@ -13,13 +13,12 @@ from igny8_core.auth.models import (
|
|||||||
Site,
|
Site,
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
from igny8_core.business.site_building.models import PageBlueprint, SiteBlueprint
|
|
||||||
|
|
||||||
|
|
||||||
class SiteBuilderTestBase(TestCase):
|
class SiteBuilderTestBase(TestCase):
|
||||||
"""
|
"""
|
||||||
Provides a lightweight set of fixtures (account/site/sector/blueprint)
|
DEPRECATED: Provides a lightweight set of fixtures (account/site/sector/blueprint)
|
||||||
so Site Builder tests can focus on service logic instead of boilerplate.
|
SiteBlueprint models have been removed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -65,20 +64,9 @@ class SiteBuilderTestBase(TestCase):
|
|||||||
account=self.account,
|
account=self.account,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.blueprint = SiteBlueprint.objects.create(
|
# DEPRECATED: SiteBlueprint and PageBlueprint models removed
|
||||||
site=self.site,
|
self.blueprint = None
|
||||||
sector=self.sector,
|
self.page_blueprint = None
|
||||||
name='Core Blueprint',
|
|
||||||
description='Initial blueprint used for tests',
|
|
||||||
hosting_type='igny8_sites',
|
|
||||||
config_json={
|
|
||||||
'business_brief': 'Default brief',
|
|
||||||
'objectives': ['Drive demos'],
|
|
||||||
'style': {'palette': 'bold'},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
self.page_blueprint = PageBlueprint.objects.create(
|
|
||||||
site_blueprint=self.blueprint,
|
|
||||||
slug='home',
|
slug='home',
|
||||||
title='Home',
|
title='Home',
|
||||||
type='home',
|
type='home',
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
"""
|
"""
|
||||||
Tests for Bulk Page Generation
|
DEPRECATED: Tests for Bulk Page Generation - SiteBlueprint models removed
|
||||||
Phase 5: Sites Renderer & Bulk Generation
|
Phase 5: Sites Renderer & Bulk Generation
|
||||||
"""
|
"""
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from unittest.mock import patch, Mock
|
from unittest.mock import patch, Mock
|
||||||
|
|
||||||
from igny8_core.auth.models import Account, Site, Sector
|
from igny8_core.auth.models import Account, Site, Sector
|
||||||
from igny8_core.business.site_building.models import SiteBlueprint, PageBlueprint
|
|
||||||
from igny8_core.business.site_building.services.page_generation_service import PageGenerationService
|
|
||||||
from igny8_core.business.content.models import Tasks
|
from igny8_core.business.content.models import Tasks
|
||||||
|
|
||||||
from .base import SiteBuilderTestBase
|
from .base import SiteBuilderTestBase
|
||||||
|
|
||||||
|
|
||||||
class BulkGenerationTestCase(SiteBuilderTestBase):
|
class BulkGenerationTestCase(SiteBuilderTestBase):
|
||||||
"""Test cases for bulk page generation"""
|
"""DEPRECATED: Test cases for bulk page generation"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Set up test data"""
|
"""Set up test data"""
|
||||||
|
|||||||
@@ -52,3 +52,9 @@ urlpatterns = [
|
|||||||
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
|
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
|
||||||
path('api/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
|
path('api/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Error handlers
|
||||||
|
handler400 = 'django.views.defaults.bad_request'
|
||||||
|
handler403 = 'django.views.defaults.permission_denied'
|
||||||
|
handler404 = 'django.views.defaults.page_not_found'
|
||||||
|
handler500 = 'django.views.defaults.server_error'
|
||||||
|
|||||||
@@ -59,6 +59,3 @@ const ActivityLog: React.FC<ActivityLogProps> = ({ runId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default ActivityLog;
|
export default ActivityLog;
|
||||||
};
|
|
||||||
|
|
||||||
export default ActivityLog;
|
|
||||||
|
|||||||
@@ -118,6 +118,3 @@ const RunHistory: React.FC<RunHistoryProps> = ({ siteId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default RunHistory;
|
export default RunHistory;
|
||||||
};
|
|
||||||
|
|
||||||
export default RunHistory;
|
|
||||||
|
|||||||
Reference in New Issue
Block a user