vscode 1
This commit is contained in:
@@ -472,3 +472,63 @@ class ContentTaxonomyRelationSerializer(serializers.ModelSerializer):
|
|||||||
def get_taxonomy_type(self, obj):
|
def get_taxonomy_type(self, obj):
|
||||||
return obj.taxonomy.taxonomy_type if obj.taxonomy else None
|
return obj.taxonomy.taxonomy_type if obj.taxonomy else None
|
||||||
|
|
||||||
|
|
||||||
|
class UpdatedTasksSerializer(serializers.ModelSerializer):
|
||||||
|
"""Updated Serializer for Tasks model with new fields."""
|
||||||
|
cluster_name = serializers.SerializerMethodField()
|
||||||
|
sector_name = serializers.SerializerMethodField()
|
||||||
|
idea_title = serializers.SerializerMethodField()
|
||||||
|
site_id = serializers.IntegerField(write_only=True, required=False)
|
||||||
|
sector_id = serializers.IntegerField(write_only=True, required=False)
|
||||||
|
content_html = serializers.SerializerMethodField()
|
||||||
|
content_primary_keyword = serializers.SerializerMethodField()
|
||||||
|
content_secondary_keywords = serializers.SerializerMethodField()
|
||||||
|
content_taxonomies = serializers.SerializerMethodField()
|
||||||
|
content_attributes = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Tasks
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
'description',
|
||||||
|
'keywords',
|
||||||
|
'cluster_id',
|
||||||
|
'cluster_name',
|
||||||
|
'sector_name',
|
||||||
|
'idea_id',
|
||||||
|
'idea_title',
|
||||||
|
'content_structure',
|
||||||
|
'content_type',
|
||||||
|
'status',
|
||||||
|
'content',
|
||||||
|
'word_count',
|
||||||
|
'meta_title',
|
||||||
|
'meta_description',
|
||||||
|
'content_html',
|
||||||
|
'content_primary_keyword',
|
||||||
|
'content_secondary_keywords',
|
||||||
|
'content_taxonomies',
|
||||||
|
'content_attributes',
|
||||||
|
'assigned_post_id',
|
||||||
|
'post_url',
|
||||||
|
'created_at',
|
||||||
|
'updated_at',
|
||||||
|
'site_id',
|
||||||
|
'sector_id',
|
||||||
|
'account_id',
|
||||||
|
]
|
||||||
|
read_only_fields = ['id', 'created_at', 'updated_at', 'account_id']
|
||||||
|
|
||||||
|
def get_content_taxonomies(self, obj):
|
||||||
|
"""Fetch related taxonomies."""
|
||||||
|
return ContentTaxonomyRelationSerializer(
|
||||||
|
obj.content.taxonomies.all(), many=True
|
||||||
|
).data
|
||||||
|
|
||||||
|
def get_content_attributes(self, obj):
|
||||||
|
"""Fetch related attributes."""
|
||||||
|
return ContentAttributeSerializer(
|
||||||
|
obj.content.attributes.all(), many=True
|
||||||
|
).data
|
||||||
|
|
||||||
|
|||||||
48
backend/migrations/0006_migrate_legacy_fields.py
Normal file
48
backend/migrations/0006_migrate_legacy_fields.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
def migrate_legacy_fields(apps, schema_editor):
|
||||||
|
Content = apps.get_model('igny8_core', 'Content')
|
||||||
|
Task = apps.get_model('igny8_core', 'Task')
|
||||||
|
|
||||||
|
# Migrate legacy fields in Content model
|
||||||
|
for content in Content.objects.all():
|
||||||
|
if content.categories:
|
||||||
|
# Convert JSON categories to ContentTaxonomy
|
||||||
|
categories = content.categories
|
||||||
|
for category in categories:
|
||||||
|
taxonomy, created = ContentTaxonomy.objects.get_or_create(
|
||||||
|
name=category['name'],
|
||||||
|
slug=category['slug'],
|
||||||
|
taxonomy_type='category'
|
||||||
|
)
|
||||||
|
content.taxonomies.add(taxonomy)
|
||||||
|
|
||||||
|
if content.tags:
|
||||||
|
# Convert JSON tags to ContentTaxonomy
|
||||||
|
tags = content.tags
|
||||||
|
for tag in tags:
|
||||||
|
taxonomy, created = ContentTaxonomy.objects.get_or_create(
|
||||||
|
name=tag['name'],
|
||||||
|
slug=tag['slug'],
|
||||||
|
taxonomy_type='tag'
|
||||||
|
)
|
||||||
|
content.taxonomies.add(taxonomy)
|
||||||
|
|
||||||
|
content.save()
|
||||||
|
|
||||||
|
# Migrate legacy fields in Task model
|
||||||
|
for task in Task.objects.all():
|
||||||
|
task.entity_type = task.content.entity_type
|
||||||
|
task.cluster_role = task.content.cluster_role
|
||||||
|
task.cluster_id = task.content.cluster_id
|
||||||
|
task.save()
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('igny8_core', '0005_phase3_mark_deprecated_fields'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(migrate_legacy_fields),
|
||||||
|
]
|
||||||
@@ -23,7 +23,9 @@ import {
|
|||||||
import {
|
import {
|
||||||
fetchTasks,
|
fetchTasks,
|
||||||
fetchContent,
|
fetchContent,
|
||||||
fetchContentImages
|
fetchContentImages,
|
||||||
|
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";
|
||||||
@@ -66,6 +68,8 @@ interface WriterStats {
|
|||||||
avgGenerationTime: number;
|
avgGenerationTime: number;
|
||||||
publishRate: number;
|
publishRate: number;
|
||||||
};
|
};
|
||||||
|
taxonomies: number;
|
||||||
|
attributes: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function WriterDashboard() {
|
export default function WriterDashboard() {
|
||||||
@@ -81,10 +85,12 @@ export default function WriterDashboard() {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const [tasksRes, contentRes, imagesRes] = await Promise.all([
|
const [tasksRes, contentRes, imagesRes, taxonomiesRes, attributesRes] = 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({ sector_id: activeSector?.id }),
|
||||||
|
fetchAttributes({ sector_id: activeSector?.id }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const tasks = tasksRes.results || [];
|
const tasks = tasksRes.results || [];
|
||||||
@@ -143,6 +149,12 @@ 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;
|
||||||
|
|
||||||
|
const taxonomies = taxonomiesRes.results || [];
|
||||||
|
const attributes = attributesRes.results || [];
|
||||||
|
|
||||||
|
const taxonomyCount = taxonomies.length;
|
||||||
|
const attributeCount = attributes.length;
|
||||||
|
|
||||||
setStats({
|
setStats({
|
||||||
tasks: {
|
tasks: {
|
||||||
total: tasks.length,
|
total: tasks.length,
|
||||||
@@ -180,7 +192,9 @@ export default function WriterDashboard() {
|
|||||||
contentThisMonth,
|
contentThisMonth,
|
||||||
avgGenerationTime: 0,
|
avgGenerationTime: 0,
|
||||||
publishRate
|
publishRate
|
||||||
}
|
},
|
||||||
|
taxonomies: taxonomyCount,
|
||||||
|
attributes: attributeCount,
|
||||||
});
|
});
|
||||||
|
|
||||||
setLastUpdated(new Date());
|
setLastUpdated(new Date());
|
||||||
@@ -239,6 +253,24 @@ export default function WriterDashboard() {
|
|||||||
count: stats?.content.published || 0,
|
count: stats?.content.published || 0,
|
||||||
metric: "View all published",
|
metric: "View all published",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "Taxonomies",
|
||||||
|
description: "Manage content taxonomies",
|
||||||
|
icon: BoltIcon,
|
||||||
|
color: "from-[var(--color-info)] to-[var(--color-info-dark)]",
|
||||||
|
path: "/writer/taxonomies",
|
||||||
|
count: stats?.taxonomies || 0,
|
||||||
|
metric: `${stats?.taxonomies || 0} total`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Attributes",
|
||||||
|
description: "Manage content attributes",
|
||||||
|
icon: PlugInIcon,
|
||||||
|
color: "from-[var(--color-secondary)] to-[var(--color-secondary-dark)]",
|
||||||
|
path: "/writer/attributes",
|
||||||
|
count: stats?.attributes || 0,
|
||||||
|
metric: `${stats?.attributes || 0} total`,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const recentActivity = [
|
const recentActivity = [
|
||||||
|
|||||||
Reference in New Issue
Block a user