Remove obsolete workflow components from site building; delete WorkflowState model, related services, and frontend steps. Update serializers and routes to reflect the removal of the site builder wizard functionality.
This commit is contained in:
Binary file not shown.
@@ -292,57 +292,6 @@ class SiteBlueprintTaxonomy(SiteSectorBaseModel):
|
||||
return f"{self.name} ({self.get_taxonomy_type_display()})"
|
||||
|
||||
|
||||
class WorkflowState(SiteSectorBaseModel):
|
||||
"""
|
||||
Persists wizard progress + gating data for each site blueprint.
|
||||
"""
|
||||
|
||||
DEFAULT_STEP = 'business_details'
|
||||
|
||||
site_blueprint = models.OneToOneField(
|
||||
SiteBlueprint,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='workflow_state',
|
||||
help_text="Blueprint whose progress is being tracked",
|
||||
)
|
||||
current_step = models.CharField(max_length=50, default=DEFAULT_STEP)
|
||||
step_status = models.JSONField(
|
||||
default=dict,
|
||||
blank=True,
|
||||
help_text="Dictionary of step → status/progress metadata",
|
||||
)
|
||||
blocking_reason = models.TextField(blank=True, null=True, help_text="Human-readable explanation when blocked")
|
||||
completed = models.BooleanField(default=False, help_text="Marks wizard completion")
|
||||
metadata = models.JSONField(default=dict, blank=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
app_label = 'site_building'
|
||||
db_table = 'igny8_site_blueprint_workflow_states'
|
||||
verbose_name = 'Workflow State'
|
||||
verbose_name_plural = 'Workflow States'
|
||||
indexes = [
|
||||
models.Index(fields=['site_blueprint']),
|
||||
models.Index(fields=['current_step']),
|
||||
models.Index(fields=['completed']),
|
||||
]
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.site_blueprint:
|
||||
# Only set fields if blueprint has them (avoid errors if blueprint is missing fields)
|
||||
if self.site_blueprint.account_id:
|
||||
self.account_id = self.site_blueprint.account_id
|
||||
if self.site_blueprint.site_id:
|
||||
self.site_id = self.site_blueprint.site_id
|
||||
if self.site_blueprint.sector_id:
|
||||
self.sector_id = self.site_blueprint.sector_id
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return f"Workflow for {self.site_blueprint.name} ({self.current_step})"
|
||||
|
||||
|
||||
class SiteBuilderOption(models.Model):
|
||||
"""
|
||||
Base model for Site Builder dropdown metadata.
|
||||
|
||||
@@ -5,15 +5,11 @@ Site Building Services
|
||||
from igny8_core.business.site_building.services.file_management_service import SiteBuilderFileService
|
||||
from igny8_core.business.site_building.services.structure_generation_service import StructureGenerationService
|
||||
from igny8_core.business.site_building.services.page_generation_service import PageGenerationService
|
||||
from igny8_core.business.site_building.services.workflow_state_service import WorkflowStateService
|
||||
from igny8_core.business.site_building.services.taxonomy_service import TaxonomyService
|
||||
from igny8_core.business.site_building.services.wizard_context_service import WizardContextService
|
||||
|
||||
__all__ = [
|
||||
'SiteBuilderFileService',
|
||||
'StructureGenerationService',
|
||||
'PageGenerationService',
|
||||
'WorkflowStateService',
|
||||
'TaxonomyService',
|
||||
'WizardContextService',
|
||||
]
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
"""
|
||||
Reusable validation helpers for the site builder workflow.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
from igny8_core.business.site_building.models import SiteBlueprint
|
||||
|
||||
|
||||
def ensure_clusters_attached(site_blueprint: SiteBlueprint) -> bool:
|
||||
if not site_blueprint.cluster_links.exists():
|
||||
raise ValidationError("Attach at least one planner cluster before proceeding.")
|
||||
return True
|
||||
|
||||
|
||||
def ensure_taxonomies_defined(site_blueprint: SiteBlueprint) -> bool:
|
||||
if not site_blueprint.taxonomies.exists():
|
||||
raise ValidationError("Define or import at least one taxonomy to continue.")
|
||||
return True
|
||||
|
||||
|
||||
def ensure_sitemap_ready(site_blueprint: SiteBlueprint) -> bool:
|
||||
if not site_blueprint.pages.exists():
|
||||
raise ValidationError("Generate the AI sitemap before reviewing this step.")
|
||||
return True
|
||||
|
||||
|
||||
def ensure_coverage_ready(site_blueprint: SiteBlueprint) -> bool:
|
||||
incomplete = site_blueprint.cluster_links.exclude(coverage_status='complete').exists()
|
||||
if incomplete:
|
||||
raise ValidationError("Complete coverage for all attached clusters.")
|
||||
return True
|
||||
|
||||
|
||||
def ensure_ideas_ready(site_blueprint: SiteBlueprint) -> bool:
|
||||
if not site_blueprint.cluster_links.exists() or not site_blueprint.pages.exists():
|
||||
raise ValidationError("Attach clusters and generate pages before sending ideas.")
|
||||
return True
|
||||
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
"""
|
||||
Wizard Context Service
|
||||
Provides aggregated data for the site builder wizard UI.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import Counter
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from django.db.models import Prefetch
|
||||
|
||||
from igny8_core.business.planning.models import Clusters
|
||||
from igny8_core.business.site_building.models import (
|
||||
PageBlueprint,
|
||||
SiteBlueprint,
|
||||
SiteBlueprintCluster,
|
||||
SiteBlueprintTaxonomy,
|
||||
)
|
||||
from igny8_core.business.site_building.services.workflow_state_service import WorkflowStateService
|
||||
|
||||
|
||||
class WizardContextService:
|
||||
"""Builds blueprint-centric context for the guided wizard experience."""
|
||||
|
||||
def __init__(self):
|
||||
self.workflow_service = WorkflowStateService()
|
||||
|
||||
def build_context(self, site_blueprint: SiteBlueprint) -> Dict[str, object]:
|
||||
if not site_blueprint:
|
||||
return {}
|
||||
|
||||
workflow_state = None
|
||||
if self.workflow_service.enabled:
|
||||
workflow_state = self.workflow_service.refresh_state(site_blueprint)
|
||||
|
||||
workflow_payload = self.workflow_service.serialize_state(workflow_state) if workflow_state else None
|
||||
|
||||
coverage_data = self._coverage_summary(site_blueprint)
|
||||
context = {
|
||||
'workflow': workflow_payload,
|
||||
'cluster_summary': self._cluster_summary(site_blueprint),
|
||||
'taxonomy_summary': self._taxonomy_summary(site_blueprint),
|
||||
'sitemap_summary': coverage_data, # Frontend expects 'sitemap_summary' not 'coverage'
|
||||
'coverage': coverage_data, # Keep for backward compatibility
|
||||
}
|
||||
context['next_actions'] = self._next_actions(workflow_payload)
|
||||
return context
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Private helpers
|
||||
# ------------------------------------------------------------------
|
||||
def _cluster_summary(self, site_blueprint: SiteBlueprint) -> Dict[str, object]:
|
||||
cluster_links: List[SiteBlueprintCluster] = list(
|
||||
site_blueprint.cluster_links.select_related('cluster')
|
||||
)
|
||||
coverage_counts = Counter(link.coverage_status for link in cluster_links)
|
||||
|
||||
clusters_payload = []
|
||||
for link in cluster_links:
|
||||
cluster = link.cluster
|
||||
dimension_meta = cluster.dimension_meta or {}
|
||||
clusters_payload.append({
|
||||
'id': cluster.id,
|
||||
'name': cluster.name,
|
||||
'context_type': cluster.context_type,
|
||||
'dimension_meta': dimension_meta,
|
||||
'keyword_count': cluster.keywords_count,
|
||||
'volume': cluster.volume,
|
||||
'coverage_status': link.coverage_status,
|
||||
'role': link.role,
|
||||
'metadata': link.metadata or {},
|
||||
'suggested_taxonomies': dimension_meta.get('suggested_taxonomies', []),
|
||||
'attribute_hints': dimension_meta.get('attributes', []),
|
||||
})
|
||||
|
||||
return {
|
||||
'attached_count': len(cluster_links),
|
||||
'coverage_counts': dict(coverage_counts),
|
||||
'clusters': clusters_payload,
|
||||
}
|
||||
|
||||
def _taxonomy_summary(self, site_blueprint: SiteBlueprint) -> Dict[str, object]:
|
||||
taxonomies: List[SiteBlueprintTaxonomy] = list(
|
||||
site_blueprint.taxonomies.prefetch_related(
|
||||
Prefetch('clusters', queryset=Clusters.objects.only('id'))
|
||||
)
|
||||
)
|
||||
|
||||
counts_by_type = Counter(taxonomy.taxonomy_type for taxonomy in taxonomies)
|
||||
taxonomy_payload = []
|
||||
for taxonomy in taxonomies:
|
||||
taxonomy_payload.append({
|
||||
'id': taxonomy.id,
|
||||
'name': taxonomy.name,
|
||||
'slug': taxonomy.slug,
|
||||
'taxonomy_type': taxonomy.taxonomy_type,
|
||||
'description': taxonomy.description,
|
||||
'cluster_ids': [cluster.id for cluster in taxonomy.clusters.all()],
|
||||
'metadata': taxonomy.metadata or {},
|
||||
'external_reference': taxonomy.external_reference,
|
||||
})
|
||||
|
||||
return {
|
||||
'total_taxonomies': len(taxonomies),
|
||||
'counts_by_type': dict(counts_by_type),
|
||||
'taxonomies': taxonomy_payload,
|
||||
}
|
||||
|
||||
def _coverage_summary(self, site_blueprint: SiteBlueprint) -> Dict[str, object]:
|
||||
pages: List[PageBlueprint] = list(site_blueprint.pages.all())
|
||||
per_status = Counter(page.status for page in pages)
|
||||
per_type = Counter(page.type for page in pages)
|
||||
|
||||
return {
|
||||
'pages_total': len(pages),
|
||||
'pages_by_status': dict(per_status),
|
||||
'pages_by_type': dict(per_type),
|
||||
}
|
||||
|
||||
def _next_actions(self, workflow_payload: Optional[Dict[str, object]]) -> Optional[Dict[str, object]]:
|
||||
if not workflow_payload:
|
||||
return None
|
||||
|
||||
for step in workflow_payload.get('steps', []):
|
||||
if step.get('status') != 'ready':
|
||||
return {
|
||||
'step': step.get('step'),
|
||||
'status': step.get('status'),
|
||||
'message': step.get('message'),
|
||||
'code': step.get('code'),
|
||||
}
|
||||
return {
|
||||
'step': None,
|
||||
'status': 'ready',
|
||||
'message': None,
|
||||
'code': None,
|
||||
}
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
"""
|
||||
Workflow State Service
|
||||
Manages wizard progress + gating checks for site blueprints.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils import timezone
|
||||
|
||||
from igny8_core.business.site_building.models import SiteBlueprint, WorkflowState
|
||||
from igny8_core.business.site_building.services import validators
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DEFAULT_STEPS: List[str] = [
|
||||
'business_details',
|
||||
'clusters',
|
||||
'taxonomies',
|
||||
'sitemap',
|
||||
'coverage',
|
||||
'ideas',
|
||||
]
|
||||
|
||||
STEP_VALIDATORS = {
|
||||
'clusters': validators.ensure_clusters_attached,
|
||||
'taxonomies': validators.ensure_taxonomies_defined,
|
||||
'sitemap': validators.ensure_sitemap_ready,
|
||||
'coverage': validators.ensure_coverage_ready,
|
||||
'ideas': validators.ensure_ideas_ready,
|
||||
}
|
||||
|
||||
STEP_CODES = {
|
||||
'business_details': 'missing_business_details',
|
||||
'clusters': 'missing_clusters',
|
||||
'taxonomies': 'missing_taxonomies',
|
||||
'sitemap': 'sitemap_not_generated',
|
||||
'coverage': 'coverage_incomplete',
|
||||
'ideas': 'ideas_not_ready',
|
||||
}
|
||||
|
||||
|
||||
class WorkflowStateService:
|
||||
"""Centralizes workflow persistence + validation logic."""
|
||||
|
||||
def __init__(self):
|
||||
self.enabled = getattr(settings, 'USE_SITE_BUILDER_REFACTOR', False)
|
||||
|
||||
def initialize(self, site_blueprint: SiteBlueprint) -> Optional[WorkflowState]:
|
||||
if not self.enabled or not site_blueprint:
|
||||
return None
|
||||
|
||||
state, _ = WorkflowState.objects.get_or_create(
|
||||
site_blueprint=site_blueprint,
|
||||
defaults={
|
||||
'current_step': WorkflowState.DEFAULT_STEP,
|
||||
'step_status': {},
|
||||
},
|
||||
)
|
||||
return state
|
||||
|
||||
def refresh_state(self, site_blueprint: SiteBlueprint) -> Optional[WorkflowState]:
|
||||
"""Re-run validators to keep the state snapshot fresh."""
|
||||
state = self.initialize(site_blueprint)
|
||||
if not state:
|
||||
return None
|
||||
timestamp = timezone.now().isoformat()
|
||||
step_status: Dict[str, Dict[str, str]] = state.step_status or {}
|
||||
blocking_reason = None
|
||||
|
||||
for step in DEFAULT_STEPS:
|
||||
validator = STEP_VALIDATORS.get(step)
|
||||
try:
|
||||
if validator:
|
||||
validator(site_blueprint)
|
||||
step_status[step] = self._build_step_entry(
|
||||
step=step,
|
||||
status='ready',
|
||||
message=None,
|
||||
timestamp=timestamp,
|
||||
)
|
||||
except ValidationError as exc:
|
||||
message = str(exc)
|
||||
step_status[step] = self._build_step_entry(
|
||||
step=step,
|
||||
status='blocked',
|
||||
message=message,
|
||||
timestamp=timestamp,
|
||||
)
|
||||
if not blocking_reason:
|
||||
blocking_reason = message
|
||||
self._emit_event(site_blueprint, 'wizard_blocking_issue', {
|
||||
'step': step,
|
||||
'message': message,
|
||||
})
|
||||
|
||||
state.step_status = step_status
|
||||
state.blocking_reason = blocking_reason
|
||||
state.completed = all(value.get('status') == 'ready' for value in step_status.values())
|
||||
|
||||
# Ensure account/site/sector are set from blueprint before saving
|
||||
update_fields = ['step_status', 'blocking_reason', 'completed', 'updated_at']
|
||||
if state.site_blueprint:
|
||||
if state.site_blueprint.account_id:
|
||||
state.account_id = state.site_blueprint.account_id
|
||||
update_fields.append('account')
|
||||
if state.site_blueprint.site_id:
|
||||
state.site_id = state.site_blueprint.site_id
|
||||
update_fields.append('site')
|
||||
if state.site_blueprint.sector_id:
|
||||
state.sector_id = state.site_blueprint.sector_id
|
||||
update_fields.append('sector')
|
||||
|
||||
try:
|
||||
state.save(update_fields=update_fields)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Failed to save workflow state for blueprint {site_blueprint.id}: {str(e)}. "
|
||||
f"Blueprint fields: account_id={site_blueprint.account_id}, site_id={site_blueprint.site_id}, sector_id={site_blueprint.sector_id}",
|
||||
exc_info=True
|
||||
)
|
||||
raise
|
||||
return state
|
||||
|
||||
def update_step(
|
||||
self,
|
||||
site_blueprint: SiteBlueprint,
|
||||
step: str,
|
||||
status: str,
|
||||
metadata: Optional[Dict[str, str]] = None,
|
||||
) -> Optional[WorkflowState]:
|
||||
"""Persist explicit step updates coming from the wizard."""
|
||||
if not self.enabled:
|
||||
return None
|
||||
|
||||
state = self.initialize(site_blueprint)
|
||||
if not state:
|
||||
return None
|
||||
|
||||
metadata = metadata or {}
|
||||
timestamp = timezone.now().isoformat()
|
||||
|
||||
# Ensure step_status is a dict (handle None case)
|
||||
if state.step_status is None:
|
||||
state.step_status = {}
|
||||
step_status = dict(state.step_status) # Create a copy to avoid mutation issues
|
||||
|
||||
entry = self._build_step_entry(
|
||||
step=step,
|
||||
status=status,
|
||||
message=metadata.get('message'),
|
||||
timestamp=timestamp,
|
||||
)
|
||||
entry.update({k: v for k, v in metadata.items() if k not in entry})
|
||||
step_status[step] = entry
|
||||
|
||||
if step in DEFAULT_STEPS:
|
||||
state.current_step = step
|
||||
|
||||
state.step_status = step_status
|
||||
state.blocking_reason = metadata.get('message')
|
||||
|
||||
# Calculate completed status - only true if all steps are ready and we have at least one step
|
||||
if step_status:
|
||||
state.completed = all(
|
||||
value.get('status') == 'ready' or value.get('status') == 'complete'
|
||||
for value in step_status.values()
|
||||
)
|
||||
else:
|
||||
state.completed = False
|
||||
|
||||
# Ensure account/site/sector are set from blueprint before saving
|
||||
update_fields = ['current_step', 'step_status', 'blocking_reason', 'completed', 'updated_at']
|
||||
if state.site_blueprint:
|
||||
if state.site_blueprint.account_id:
|
||||
state.account_id = state.site_blueprint.account_id
|
||||
update_fields.append('account')
|
||||
if state.site_blueprint.site_id:
|
||||
state.site_id = state.site_blueprint.site_id
|
||||
update_fields.append('site')
|
||||
if state.site_blueprint.sector_id:
|
||||
state.sector_id = state.site_blueprint.sector_id
|
||||
update_fields.append('sector')
|
||||
|
||||
try:
|
||||
state.save(update_fields=update_fields)
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Failed to save workflow state for blueprint {site_blueprint.id}: {str(e)}. "
|
||||
f"Blueprint fields: account_id={site_blueprint.account_id}, site_id={site_blueprint.site_id}, sector_id={site_blueprint.sector_id}",
|
||||
exc_info=True
|
||||
)
|
||||
raise
|
||||
|
||||
self._emit_event(site_blueprint, 'wizard_step_updated', {
|
||||
'step': step,
|
||||
'status': status,
|
||||
})
|
||||
return state
|
||||
|
||||
def validate_step(self, site_blueprint: SiteBlueprint, step: str) -> None:
|
||||
"""Run validator for a single step (raises ValidationError when blocked)."""
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
validator = STEP_VALIDATORS.get(step)
|
||||
if not validator:
|
||||
return
|
||||
|
||||
validator(site_blueprint)
|
||||
|
||||
def serialize_state(self, state: Optional[WorkflowState]) -> Optional[Dict[str, object]]:
|
||||
"""Return a stable payload for API consumers."""
|
||||
if not self.enabled or not state:
|
||||
return None
|
||||
|
||||
step_status = state.step_status or {}
|
||||
steps_payload = []
|
||||
for step in DEFAULT_STEPS:
|
||||
meta = step_status.get(step, {})
|
||||
steps_payload.append({
|
||||
'step': step,
|
||||
'status': meta.get('status', 'pending'),
|
||||
'code': meta.get('code') or STEP_CODES.get(step),
|
||||
'message': meta.get('message'),
|
||||
'updated_at': meta.get('updated_at') or state.updated_at.isoformat(),
|
||||
})
|
||||
|
||||
return {
|
||||
'current_step': state.current_step,
|
||||
'completed': state.completed,
|
||||
'blocking_reason': state.blocking_reason,
|
||||
'steps': steps_payload,
|
||||
'updated_at': state.updated_at.isoformat() if hasattr(state.updated_at, 'isoformat') else str(state.updated_at),
|
||||
}
|
||||
|
||||
def _build_step_entry(
|
||||
self,
|
||||
step: str,
|
||||
status: str,
|
||||
message: Optional[str],
|
||||
timestamp: str,
|
||||
) -> Dict[str, Optional[str]]:
|
||||
return {
|
||||
'status': status,
|
||||
'code': STEP_CODES.get(step),
|
||||
'message': message,
|
||||
'updated_at': timestamp,
|
||||
}
|
||||
|
||||
def _emit_event(self, site_blueprint: SiteBlueprint, event: str, payload: Optional[Dict[str, object]] = None) -> None:
|
||||
if not self.enabled:
|
||||
return
|
||||
payload = payload or {}
|
||||
logger.info(
|
||||
"Wizard event: %s blueprint=%s site=%s account=%s payload=%s",
|
||||
event,
|
||||
site_blueprint.id,
|
||||
site_blueprint.site_id,
|
||||
site_blueprint.account_id,
|
||||
payload,
|
||||
)
|
||||
|
||||
@@ -8,9 +8,7 @@ from igny8_core.business.site_building.models import (
|
||||
HeroImageryDirection,
|
||||
PageBlueprint,
|
||||
SiteBlueprint,
|
||||
WorkflowState,
|
||||
)
|
||||
from igny8_core.business.site_building.services.workflow_state_service import WorkflowStateService
|
||||
|
||||
|
||||
class PageBlueprintSerializer(serializers.ModelSerializer):
|
||||
@@ -48,8 +46,6 @@ class SiteBlueprintSerializer(serializers.ModelSerializer):
|
||||
site_id = serializers.IntegerField(required=False, read_only=True)
|
||||
sector_id = serializers.IntegerField(required=False, read_only=True)
|
||||
account_id = serializers.IntegerField(read_only=True)
|
||||
workflow_state = serializers.SerializerMethodField()
|
||||
gating_messages = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = SiteBlueprint
|
||||
@@ -69,8 +65,6 @@ class SiteBlueprintSerializer(serializers.ModelSerializer):
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'pages',
|
||||
'workflow_state',
|
||||
'gating_messages',
|
||||
]
|
||||
read_only_fields = [
|
||||
'structure_json',
|
||||
@@ -92,33 +86,6 @@ class SiteBlueprintSerializer(serializers.ModelSerializer):
|
||||
attrs['sector_id'] = sector_id
|
||||
return attrs
|
||||
|
||||
def get_workflow_state(self, obj):
|
||||
return self._get_workflow_payload(obj)
|
||||
|
||||
def get_gating_messages(self, obj):
|
||||
workflow_payload = self._get_workflow_payload(obj)
|
||||
if not workflow_payload:
|
||||
return None
|
||||
blocked = [step for step in workflow_payload.get('steps', []) if step.get('status') == 'blocked']
|
||||
return blocked or None
|
||||
|
||||
def _get_workflow_payload(self, obj):
|
||||
if not getattr(settings, 'USE_SITE_BUILDER_REFACTOR', False):
|
||||
return None
|
||||
cache = self.context.setdefault('_workflow_state_cache', {})
|
||||
if obj.id in cache:
|
||||
return cache[obj.id]
|
||||
try:
|
||||
state: WorkflowState = obj.workflow_state
|
||||
except WorkflowState.DoesNotExist:
|
||||
state = None
|
||||
service = getattr(self, '_workflow_service', None)
|
||||
if service is None:
|
||||
service = WorkflowStateService()
|
||||
self._workflow_service = service
|
||||
payload = service.serialize_state(state)
|
||||
cache[obj.id] = payload
|
||||
return payload
|
||||
|
||||
|
||||
class MetadataOptionSerializer(serializers.Serializer):
|
||||
|
||||
@@ -28,7 +28,6 @@ from igny8_core.business.site_building.services import (
|
||||
SiteBuilderFileService,
|
||||
StructureGenerationService,
|
||||
TaxonomyService,
|
||||
WizardContextService,
|
||||
)
|
||||
from igny8_core.modules.site_builder.serializers import (
|
||||
PageBlueprintSerializer,
|
||||
@@ -51,7 +50,6 @@ class SiteBlueprintViewSet(SiteSectorModelViewSet):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.taxonomy_service = TaxonomyService()
|
||||
self.wizard_context_service = WizardContextService()
|
||||
|
||||
def get_permissions(self):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user