imp part 3
This commit is contained in:
17
IGNY8-APP.md
17
IGNY8-APP.md
@@ -246,8 +246,21 @@ Stage 7: Generate images → Review queue
|
||||
| **Usage** | ✅ Active | `/account/usage` |
|
||||
| **AI Models** | ✅ Active (Admin) | `/settings/integration` |
|
||||
| **Help** | ✅ Active | `/help` |
|
||||
| **Linker** | ⏸️ Disabled | Internal linking (available, disabled by default) |
|
||||
| **Optimizer** | ⏸️ Disabled | Content optimization (available, disabled by default) |
|
||||
| **SiteBuilder** | ❌ Deprecated | Removed - was for site structure generation |
|
||||
| **Linker** | ⏸️ Phase 2 | Internal linking suggestions (disabled by default) |
|
||||
| **Optimizer** | ⏸️ Phase 2 | Content optimization (disabled by default) |
|
||||
|
||||
### Module Status Details
|
||||
|
||||
| Module | Status | Notes |
|
||||
|--------|--------|-------|
|
||||
| **SiteBuilder** | ❌ Deprecated | Code exists but feature is removed. Marked for cleanup. |
|
||||
| **Linker** | ⏸️ Phase 2 | Feature flag: `linker_enabled`. Available but disabled by default. |
|
||||
| **Optimizer** | ⏸️ Phase 2 | Feature flag: `optimizer_enabled`. Available but disabled by default. |
|
||||
|
||||
To enable Phase 2 modules, update via Django Admin:
|
||||
- `GlobalModuleSettings` (pk=1) for platform-wide settings
|
||||
- `ModuleEnableSettings` for per-account settings
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -591,7 +591,11 @@ class AICore:
|
||||
image_url = image_data.get('url')
|
||||
revised_prompt = image_data.get('revised_prompt')
|
||||
|
||||
cost = IMAGE_MODEL_RATES.get(model, 0.040) * n
|
||||
# Use ModelRegistry for image cost (with fallback to constants)
|
||||
from igny8_core.ai.model_registry import ModelRegistry
|
||||
cost = float(ModelRegistry.calculate_cost(model, num_images=n))
|
||||
if cost == 0:
|
||||
cost = IMAGE_MODEL_RATES.get(model, 0.040) * n
|
||||
print(f"[AI][{function_name}] Step 5: Image generated successfully")
|
||||
print(f"[AI][{function_name}] Step 6: Cost: ${cost:.4f}")
|
||||
print(f"[AI][{function_name}][Success] Image generation completed")
|
||||
@@ -827,15 +831,24 @@ class AICore:
|
||||
}
|
||||
|
||||
def calculate_cost(self, model: str, input_tokens: int, output_tokens: int, model_type: str = 'text') -> float:
|
||||
"""Calculate cost for API call"""
|
||||
"""Calculate cost for API call using ModelRegistry with fallback to constants"""
|
||||
from igny8_core.ai.model_registry import ModelRegistry
|
||||
|
||||
if model_type == 'text':
|
||||
rates = MODEL_RATES.get(model, {'input': 2.00, 'output': 8.00})
|
||||
input_cost = (input_tokens / 1_000_000) * rates['input']
|
||||
output_cost = (output_tokens / 1_000_000) * rates['output']
|
||||
return input_cost + output_cost
|
||||
cost = float(ModelRegistry.calculate_cost(model, input_tokens=input_tokens, output_tokens=output_tokens))
|
||||
if cost == 0:
|
||||
# Fallback to constants
|
||||
rates = MODEL_RATES.get(model, {'input': 2.00, 'output': 8.00})
|
||||
input_cost = (input_tokens / 1_000_000) * rates['input']
|
||||
output_cost = (output_tokens / 1_000_000) * rates['output']
|
||||
return input_cost + output_cost
|
||||
return cost
|
||||
elif model_type == 'image':
|
||||
rate = IMAGE_MODEL_RATES.get(model, 0.040)
|
||||
return rate * 1
|
||||
cost = float(ModelRegistry.calculate_cost(model, num_images=1))
|
||||
if cost == 0:
|
||||
rate = IMAGE_MODEL_RATES.get(model, 0.040)
|
||||
return rate * 1
|
||||
return cost
|
||||
return 0.0
|
||||
|
||||
# Legacy method names for backward compatibility
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from django.db import models
|
||||
from igny8_core.auth.models import SiteSectorBaseModel, SeedKeyword
|
||||
from igny8_core.common.soft_delete import SoftDeletableModel, SoftDeleteManager
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Clusters(SoftDeletableModel, SiteSectorBaseModel):
|
||||
@@ -40,6 +43,27 @@ class Clusters(SoftDeletableModel, SiteSectorBaseModel):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def soft_delete(self, user=None, reason=None, retention_days=None):
|
||||
"""
|
||||
Override soft_delete to cascade status reset to related Keywords.
|
||||
When a cluster is deleted, its keywords should:
|
||||
- Have their cluster FK set to NULL (handled by SET_NULL)
|
||||
- Have their status reset to 'new' (orphaned keywords)
|
||||
"""
|
||||
# Reset related keywords status to 'new' and clear cluster FK
|
||||
keywords_count = self.keywords.filter(is_deleted=False).update(
|
||||
cluster=None,
|
||||
status='new'
|
||||
)
|
||||
|
||||
logger.info(
|
||||
f"[Clusters.soft_delete] Cluster {self.id} '{self.name}' cascade: "
|
||||
f"reset {keywords_count} keywords to status='new'"
|
||||
)
|
||||
|
||||
# Call parent soft_delete
|
||||
super().soft_delete(user=user, reason=reason, retention_days=retention_days)
|
||||
|
||||
|
||||
class Keywords(SoftDeletableModel, SiteSectorBaseModel):
|
||||
"""
|
||||
|
||||
@@ -146,5 +146,70 @@ Before implementing any UI element:
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: Current Session
|
||||
## 📝 Typography Scale
|
||||
|
||||
Typography tokens are defined in `index.css` and should be used consistently:
|
||||
|
||||
### Title Sizes (for page/section headings)
|
||||
| Token | Size | Line Height | Use Case |
|
||||
|-------|------|-------------|----------|
|
||||
| `--text-title-2xl` | 72px | 90px | Hero sections only |
|
||||
| `--text-title-xl` | 60px | 72px | Landing page headings |
|
||||
| `--text-title-lg` | 48px | 60px | Major section headers |
|
||||
| `--text-title-md` | 36px | 44px | Page titles |
|
||||
| `--text-title-sm` | 30px | 38px | Section subtitles |
|
||||
|
||||
### Theme Sizes (for body text)
|
||||
| Token | Size | Line Height | Use Case |
|
||||
|-------|------|-------------|----------|
|
||||
| `--text-theme-xl` | 20px | 30px | Large body text, intro paragraphs |
|
||||
| `--text-theme-sm` | 14px | 20px | Standard body text, menu items |
|
||||
| `--text-theme-xs` | 12px | 18px | Small text, labels, captions |
|
||||
|
||||
### Usage in Tailwind
|
||||
```tsx
|
||||
// Use Tailwind utilities mapped to tokens
|
||||
<h1 className="text-title-md">Page Title</h1>
|
||||
<p className="text-theme-sm">Body text</p>
|
||||
<span className="text-theme-xs">Caption</span>
|
||||
|
||||
// Or use the custom utility classes
|
||||
<h2 className="text-2xl font-semibold">Section Title</h2>
|
||||
<p className="text-base">Body text</p>
|
||||
```
|
||||
|
||||
### Font Weights
|
||||
- `font-normal` (400) - Body text
|
||||
- `font-medium` (500) - Labels, menu items
|
||||
- `font-semibold` (600) - Headings, emphasis
|
||||
- `font-bold` (700) - Strong emphasis
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Module Colors
|
||||
|
||||
Module-specific colors are defined in `src/config/colors.config.ts`:
|
||||
|
||||
| Module | Primary Color | Usage |
|
||||
|--------|---------------|-------|
|
||||
| Keywords | `brand-500` (blue) | Icons, progress bars, badges |
|
||||
| Clusters | `purple-500` | Icons, progress bars, badges |
|
||||
| Ideas | `purple-600` | Icons, progress bars, badges |
|
||||
| Tasks | `success-600` (green) | Icons, progress bars, badges |
|
||||
| Content | `success-500` | Icons, progress bars, badges |
|
||||
| Images | `purple-500` | Icons, progress bars, badges |
|
||||
| Automation | `brand-500` | Pipeline cards |
|
||||
| Billing | `warning-500` (amber) | Credit displays |
|
||||
|
||||
```tsx
|
||||
import { MODULE_COLORS } from '@/config/colors.config';
|
||||
|
||||
// Use in components
|
||||
<div className={MODULE_COLORS.keywords.bg}>Keywords Section</div>
|
||||
<span className={MODULE_COLORS.clusters.text}>Cluster Label</span>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: December 30, 2025
|
||||
**Status**: Active Design System Rules
|
||||
|
||||
@@ -175,7 +175,7 @@
|
||||
}
|
||||
|
||||
@utility menu-item {
|
||||
@apply relative flex items-center w-full gap-3 px-3.5 py-2.5 font-medium rounded-lg text-theme-sm;
|
||||
@apply relative flex items-center w-full gap-3.5 px-4 py-3 font-medium rounded-lg text-theme-sm;
|
||||
}
|
||||
|
||||
@utility menu-item-active {
|
||||
@@ -188,7 +188,7 @@
|
||||
|
||||
/* Menu icon sizing - consistent across sidebar */
|
||||
@utility menu-item-icon-size {
|
||||
@apply w-5 h-5 flex-shrink-0;
|
||||
@apply w-6 h-6 flex-shrink-0;
|
||||
|
||||
/* Force SVG icons to inherit parent size */
|
||||
& svg {
|
||||
@@ -207,7 +207,7 @@
|
||||
|
||||
/* Dropdown menu items - increased spacing */
|
||||
@utility menu-dropdown-item {
|
||||
@apply block px-3 py-2 text-theme-sm font-medium rounded-md transition-colors;
|
||||
@apply block px-3.5 py-2.5 text-theme-sm font-medium rounded-md transition-colors;
|
||||
}
|
||||
|
||||
@utility menu-dropdown-item-active {
|
||||
|
||||
Reference in New Issue
Block a user