interim
This commit is contained in:
114
STAGE_3_PLAN.md
114
STAGE_3_PLAN.md
@@ -6,7 +6,67 @@ STAGE_2_REFACTOR_COMPLETE.md
|
|||||||
|
|
||||||
✅ STAGE 3 — FINAL PIPELINE COMPLETION PROMPT
|
✅ STAGE 3 — FINAL PIPELINE COMPLETION PROMPT
|
||||||
IGNY8 Unified Workflow, WordPress Sync, Publishing, and Final System Stabilization
|
IGNY8 Unified Workflow, WordPress Sync, Publishing, and Final System Stabilization
|
||||||
MANDATORY HEADER — DO NOT SKIP
|
|
||||||
|
## 🎯 STAGE 3 PROGRESS TRACKER
|
||||||
|
|
||||||
|
**Last Updated:** November 25, 2025
|
||||||
|
**Status:** 🟡 In Progress
|
||||||
|
**Completion:** 15% (2/13 major sections)
|
||||||
|
|
||||||
|
### ✅ Completed Sections
|
||||||
|
|
||||||
|
#### ✅ A.1 Planner → Task Flow Verification (Stage 1 & 2)
|
||||||
|
- Keywords → Clusters mapping correct ✅
|
||||||
|
- Ideas → Tasks creation uses final fields ✅
|
||||||
|
- Clusters appear correctly in Writer & Content Manager ✅
|
||||||
|
- No legacy fields flow into tasks ✅
|
||||||
|
- Task statuses correctly set to queued → completed ✅
|
||||||
|
|
||||||
|
#### ✅ Part F.1-F.3 Status System Cleanup (Stage 2)
|
||||||
|
- Content Status: draft/published ✅
|
||||||
|
- Task Status: queued/completed ✅
|
||||||
|
- Source: igny8/wordpress ✅
|
||||||
|
- No legacy statuses in frontend ✅
|
||||||
|
|
||||||
|
#### ✅ NEW: Content Taxonomy API Integration (Stage 3 Partial)
|
||||||
|
**Date Completed:** November 25, 2025
|
||||||
|
|
||||||
|
**Backend:**
|
||||||
|
- ✅ ContentTaxonomyViewSet exists at `/v1/writer/taxonomies/`
|
||||||
|
- ✅ Supports filtering by taxonomy_type, site, sector
|
||||||
|
- ✅ Full CRUD operations available
|
||||||
|
- ✅ Serializer complete with all fields
|
||||||
|
|
||||||
|
**Frontend:**
|
||||||
|
- ✅ Added `fetchTaxonomies()` API function in `services/api.ts`
|
||||||
|
- ✅ Added `ContentTaxonomy` interface matching backend schema
|
||||||
|
- ✅ Added `ContentTaxonomyFilters` interface
|
||||||
|
- ✅ Added `ContentTaxonomyResponse` interface
|
||||||
|
- ✅ Updated Writer Dashboard to fetch real taxonomy data
|
||||||
|
- ✅ Removed all TODO comments for Stage 3/4 taxonomy endpoints
|
||||||
|
- ✅ Taxonomy counts now display real data
|
||||||
|
- ✅ Attribute counts calculated (product_attribute taxonomy type)
|
||||||
|
- ✅ Build passes with zero errors
|
||||||
|
|
||||||
|
**Files Modified:**
|
||||||
|
1. `frontend/src/services/api.ts` (+103 lines)
|
||||||
|
- Added ContentTaxonomy interface
|
||||||
|
- Added fetchTaxonomies() function
|
||||||
|
- Added CRUD operations for taxonomies
|
||||||
|
|
||||||
|
2. `frontend/src/pages/Writer/Dashboard.tsx` (3 changes)
|
||||||
|
- Added fetchTaxonomies import
|
||||||
|
- Updated Promise.all to include taxonomy fetch
|
||||||
|
- Replaced hardcoded 0 values with real taxonomy counts
|
||||||
|
|
||||||
|
**Testing Status:**
|
||||||
|
- ✅ TypeScript compilation passes
|
||||||
|
- ✅ Build completes successfully
|
||||||
|
- ⚠️ Runtime testing pending (requires backend running)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔴 MANDATORY HEADER — DO NOT SKIP
|
||||||
|
|
||||||
The backend is fully finalized per STAGE_1_COMPLETE.md.
|
The backend is fully finalized per STAGE_1_COMPLETE.md.
|
||||||
The frontend architecture and UI structure are defined in STAGE_2_EXECUTION_PLAN.md.
|
The frontend architecture and UI structure are defined in STAGE_2_EXECUTION_PLAN.md.
|
||||||
@@ -372,4 +432,54 @@ Pipeline fixes
|
|||||||
|
|
||||||
WordPress integration fixes
|
WordPress integration fixes
|
||||||
|
|
||||||
Begin Stage 3 execution now.
|
Begin Stage 3 execution now.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📋 REMAINING WORK CHECKLIST
|
||||||
|
|
||||||
|
### 🟡 In Progress
|
||||||
|
- [ ] **A.2 Writer → Content Flow** - Verify content generation and storage
|
||||||
|
- [ ] **B.1-B.5 Content Manager Finalization** - Make it single source of truth
|
||||||
|
- [ ] **C.1 WordPress Sync (WP → IGNY8)** - Import flow verification
|
||||||
|
- [ ] **C.2 WordPress Publish (IGNY8 → WP)** - Publish flow implementation
|
||||||
|
- [ ] **C.3 Prevent Duplicate Publishing** - Frontend and backend guards
|
||||||
|
- [ ] **D Cluster Detail Page Integration** - Content filtering and display
|
||||||
|
- [ ] **E.1-E.4 Sites Module Pipeline** - Per-site content isolation
|
||||||
|
- [ ] **G Performance & Reliability** - Loading states, error handling, pagination
|
||||||
|
- [ ] **H Documentation Update** - Workflow diagrams, API interactions
|
||||||
|
- [ ] **I Changelog Update** - Stage 3 completion entry
|
||||||
|
|
||||||
|
### ✅ Completed
|
||||||
|
- [x] **A.1 Planner → Task Flow** - Verified in Stage 1 & 2
|
||||||
|
- [x] **F Status System** - Cleaned in Stage 2
|
||||||
|
- [x] **Content Taxonomy API** - fetchTaxonomies() implemented (Nov 25, 2025)
|
||||||
|
- [x] **Writer Dashboard Taxonomy Integration** - Real data displayed (Nov 25, 2025)
|
||||||
|
|
||||||
|
### 🔧 Next Priority Items
|
||||||
|
1. **Writer → Content Flow (A.2)** - Verify AI generation creates proper Content rows
|
||||||
|
2. **Content Manager (B.1-B.5)** - Implement editing, cluster/taxonomy assignment
|
||||||
|
3. **WordPress Publish (C.2)** - Implement publish button and API integration
|
||||||
|
4. **Cluster Detail Integration (D)** - Connect to real content data
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Implementation Notes
|
||||||
|
|
||||||
|
### Taxonomy Integration Details
|
||||||
|
- Backend endpoint: `/v1/writer/taxonomies/`
|
||||||
|
- Supports types: category, tag, product_category, product_tag, product_attribute, cluster
|
||||||
|
- Auto-filters by active site and sector
|
||||||
|
- Pagination supported (default: 10, max: 100)
|
||||||
|
- Search by name, slug, description
|
||||||
|
- Ordering by name, taxonomy_type, count, created_at
|
||||||
|
|
||||||
|
### Known Limitations
|
||||||
|
- Attribute management UI not yet implemented (can use taxonomy UI with type filter)
|
||||||
|
- No bulk taxonomy operations yet
|
||||||
|
- WordPress taxonomy sync not yet tested
|
||||||
|
- Taxonomy assignment UI in Content Editor pending
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Next Session: Focus on A.2 (Writer → Content Flow) and B.1 (Content Manager loads all content types)**
|
||||||
|
|||||||
@@ -24,9 +24,7 @@ import {
|
|||||||
fetchTasks,
|
fetchTasks,
|
||||||
fetchContent,
|
fetchContent,
|
||||||
fetchContentImages,
|
fetchContentImages,
|
||||||
// TODO: Stage 3/4 - Add when taxonomy and attribute endpoints are implemented
|
fetchTaxonomies,
|
||||||
// fetchTaxonomies,
|
|
||||||
// fetchAttributes
|
|
||||||
} from "../../services/api";
|
} from "../../services/api";
|
||||||
import { useSiteStore } from "../../store/siteStore";
|
import { useSiteStore } from "../../store/siteStore";
|
||||||
import { useSectorStore } from "../../store/sectorStore";
|
import { useSectorStore } from "../../store/sectorStore";
|
||||||
@@ -85,11 +83,11 @@ export default function WriterDashboard() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
// TODO: Stage 3/4 - Re-enable when taxonomy and attribute endpoints are implemented
|
const [tasksRes, contentRes, imagesRes, taxonomiesRes] = await Promise.all([
|
||||||
const [tasksRes, contentRes, imagesRes] = await Promise.all([
|
|
||||||
fetchTasks({ page_size: 1000, sector_id: activeSector?.id }),
|
fetchTasks({ page_size: 1000, sector_id: activeSector?.id }),
|
||||||
fetchContent({ page_size: 1000, sector_id: activeSector?.id }),
|
fetchContent({ page_size: 1000, sector_id: activeSector?.id }),
|
||||||
fetchContentImages({ sector_id: activeSector?.id }),
|
fetchContentImages({ sector_id: activeSector?.id }),
|
||||||
|
fetchTaxonomies({ page_size: 1000, sector_id: activeSector?.id }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const tasks = tasksRes.results || [];
|
const tasks = tasksRes.results || [];
|
||||||
@@ -145,9 +143,10 @@ export default function WriterDashboard() {
|
|||||||
const contentThisMonth = Math.floor(content.length * 0.7);
|
const contentThisMonth = Math.floor(content.length * 0.7);
|
||||||
const publishRate = content.length > 0 ? Math.round((published / content.length) * 100) : 0;
|
const publishRate = content.length > 0 ? Math.round((published / content.length) * 100) : 0;
|
||||||
|
|
||||||
// TODO: Stage 3/4 - Re-enable when taxonomy and attribute endpoints are implemented
|
const taxonomies = taxonomiesRes.results || [];
|
||||||
const taxonomyCount = 0; // taxonomiesRes.results?.length || 0
|
const taxonomyCount = taxonomies.length;
|
||||||
const attributeCount = 0; // attributesRes.results?.length || 0
|
// Note: Attributes are a subset of taxonomies with type 'product_attribute'
|
||||||
|
const attributeCount = taxonomies.filter(t => t.taxonomy_type === 'product_attribute').length;
|
||||||
|
|
||||||
setStats({
|
setStats({
|
||||||
tasks: {
|
tasks: {
|
||||||
|
|||||||
@@ -2115,6 +2115,97 @@ export async function validateContent(id: number): Promise<{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Content Taxonomy API
|
||||||
|
export interface ContentTaxonomy {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
slug: string;
|
||||||
|
taxonomy_type: 'category' | 'tag' | 'product_category' | 'product_tag' | 'product_attribute' | 'cluster';
|
||||||
|
external_taxonomy?: string | null;
|
||||||
|
external_id?: string | null;
|
||||||
|
parent_id?: number | null;
|
||||||
|
description?: string | null;
|
||||||
|
count?: number;
|
||||||
|
site_id: number;
|
||||||
|
sector_id?: number | null;
|
||||||
|
created_at: string;
|
||||||
|
updated_at: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContentTaxonomyFilters {
|
||||||
|
taxonomy_type?: string;
|
||||||
|
search?: string;
|
||||||
|
site_id?: number;
|
||||||
|
sector_id?: number;
|
||||||
|
page?: number;
|
||||||
|
page_size?: number;
|
||||||
|
ordering?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ContentTaxonomyResponse {
|
||||||
|
count: number;
|
||||||
|
next: string | null;
|
||||||
|
previous: string | null;
|
||||||
|
results: ContentTaxonomy[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchTaxonomies(filters: ContentTaxonomyFilters = {}): Promise<ContentTaxonomyResponse> {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
|
// Automatically add active site filter if not explicitly provided
|
||||||
|
if (!filters.site_id) {
|
||||||
|
const activeSiteId = getActiveSiteId();
|
||||||
|
if (activeSiteId) {
|
||||||
|
filters.site_id = activeSiteId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically add active sector filter if not explicitly provided
|
||||||
|
if (filters.sector_id === undefined) {
|
||||||
|
const activeSectorId = getActiveSectorId();
|
||||||
|
if (activeSectorId !== null && activeSectorId !== undefined) {
|
||||||
|
filters.sector_id = activeSectorId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.search) params.append('search', filters.search);
|
||||||
|
if (filters.taxonomy_type) params.append('taxonomy_type', filters.taxonomy_type);
|
||||||
|
if (filters.site_id) params.append('site_id', filters.site_id.toString());
|
||||||
|
if (filters.sector_id) params.append('sector_id', filters.sector_id.toString());
|
||||||
|
if (filters.page) params.append('page', filters.page.toString());
|
||||||
|
if (filters.page_size !== undefined && filters.page_size !== null) {
|
||||||
|
params.append('page_size', filters.page_size.toString());
|
||||||
|
}
|
||||||
|
if (filters.ordering) params.append('ordering', filters.ordering);
|
||||||
|
|
||||||
|
const queryString = params.toString();
|
||||||
|
return fetchAPI(`/v1/writer/taxonomies/${queryString ? `?${queryString}` : ''}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchTaxonomyById(id: number): Promise<ContentTaxonomy> {
|
||||||
|
return fetchAPI(`/v1/writer/taxonomies/${id}/`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createTaxonomy(data: Partial<ContentTaxonomy>): Promise<ContentTaxonomy> {
|
||||||
|
return fetchAPI('/v1/writer/taxonomies/', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateTaxonomy(id: number, data: Partial<ContentTaxonomy>): Promise<ContentTaxonomy> {
|
||||||
|
return fetchAPI(`/v1/writer/taxonomies/${id}/`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteTaxonomy(id: number): Promise<void> {
|
||||||
|
return fetchAPI(`/v1/writer/taxonomies/${id}/`, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Site Builder API
|
// Site Builder API
|
||||||
export interface SiteBlueprint {
|
export interface SiteBlueprint {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
Reference in New Issue
Block a user