diff --git a/frontend/src/components/common/HTMLContentRenderer.tsx b/frontend/src/components/common/HTMLContentRenderer.tsx
index 14d7aa60..7b9cb4f1 100644
--- a/frontend/src/components/common/HTMLContentRenderer.tsx
+++ b/frontend/src/components/common/HTMLContentRenderer.tsx
@@ -17,7 +17,15 @@ interface HTMLContentRendererProps {
*/
function formatContentOutline(content: any): string {
if (!content) return '';
-
+
+ // If object contains a `content` field with HTML, use that directly
+ if (typeof content === 'object' && content !== null && 'content' in content) {
+ const mainContent = (content as any).content;
+ if (typeof mainContent === 'string' && mainContent.trim().length > 0) {
+ return sanitizeHTML(mainContent);
+ }
+ }
+
let html = '
';
// Handle introduction section - can be object or string
diff --git a/frontend/src/components/common/ToggleTableRow.tsx b/frontend/src/components/common/ToggleTableRow.tsx
index 3fc63b7c..9c66dfbe 100644
--- a/frontend/src/components/common/ToggleTableRow.tsx
+++ b/frontend/src/components/common/ToggleTableRow.tsx
@@ -6,6 +6,7 @@
import React, { useState, useRef, useEffect } from 'react';
import { ChevronDownIcon, HorizontaLDots } from '../../icons';
import HTMLContentRenderer from './HTMLContentRenderer';
+import Badge from '../ui/badge/Badge';
interface ToggleTableRowProps {
/** The row data */
@@ -44,6 +45,13 @@ const ToggleTableRow: React.FC
= ({
// Get content - handle fallback to description if primary contentKey is empty
let content = row[contentKey];
+ let contentMetadata: Record | null = null;
+
+ if (content && typeof content === 'object' && content !== null && 'content' in content) {
+ contentMetadata = { ...content };
+ content = content.content;
+ }
+
if (!content || (typeof content === 'string' && content.trim().length === 0)) {
// Try fallback to description if primary content is empty
content = row.description || row.content_outline || null;
@@ -104,9 +112,157 @@ const ToggleTableRow: React.FC = ({
className="overflow-hidden"
>
-
- {contentLabel}
+
+
+ {contentLabel}
+
+
+ {/* Metadata badges */}
+
+
+ {/* Rendered content */}
+
+
+
+
+
+
+
+ );
+};
+
+interface ToggleMetadataProps {
+ row: any;
+ contentMetadata: Record | null;
+}
+
+const ToggleMetadata: React.FC = ({ row, contentMetadata }) => {
+ const primaryKeyword =
+ row.content_primary_keyword ||
+ row.primary_keyword ||
+ contentMetadata?.primary_keyword ||
+ contentMetadata?.metadata?.primary_keyword ||
+ null;
+
+ const secondaryKeywords =
+ row.content_secondary_keywords ||
+ row.secondary_keywords ||
+ contentMetadata?.secondary_keywords ||
+ contentMetadata?.metadata?.secondary_keywords ||
+ [];
+
+ const tags =
+ row.content_tags ||
+ row.tags ||
+ contentMetadata?.tags ||
+ contentMetadata?.metadata?.tags ||
+ [];
+
+ const categories =
+ row.content_categories ||
+ row.categories ||
+ contentMetadata?.categories ||
+ contentMetadata?.metadata?.categories ||
+ [];
+
+ const metaDescription =
+ row.meta_description ||
+ row.content_meta_description ||
+ contentMetadata?.meta_description ||
+ contentMetadata?.metadata?.meta_description ||
+ null;
+
+ const hasMetadata =
+ primaryKeyword ||
+ (secondaryKeywords && secondaryKeywords.length > 0) ||
+ (tags && tags.length > 0) ||
+ (categories && categories.length > 0) ||
+ metaDescription;
+
+ if (!hasMetadata) {
+ return null;
+ }
+
+ const renderBadgeList = (items: any, color: 'info' | 'light' = 'light') => {
+ if (!items) return null;
+ const list = Array.isArray(items) ? items : [items];
+ if (list.length === 0) return null;
+
+ return (
+
+ {list.map((item, index) => (
+
+ {item}
+
+ ))}
+
+ );
+ };
+
+ return (
+
+ {primaryKeyword && (
+
+ Primary Keyword:
+
+ {primaryKeyword}
+
+
+ )}
+
+ {(() => {
+ const badges = renderBadgeList(secondaryKeywords);
+ if (!badges) return null;
+ return (
+
+ Secondary Keywords:
+ {badges}
+
+ );
+ })()}
+
+ {(() => {
+ const badges = renderBadgeList(tags);
+ if (!badges) return null;
+ return (
+
+ Tags:
+ {badges}
+
+ );
+ })()}
+
+ {(() => {
+ const badges = renderBadgeList(categories);
+ if (!badges) return null;
+ return (
+
+ Categories:
+ {badges}
+
+ );
+ })()}
+
+ {metaDescription && (
+
+
+ Meta Description
+
+ {metaDescription}
+
+ )}
+
+ );
+};
{
+ const getList = (primary?: string[], fallback?: any): string[] => {
+ if (primary && primary.length > 0) return primary;
+ if (!fallback) return [];
+ if (Array.isArray(fallback)) return fallback;
+ return [];
+ };
+
+ const renderBadgeList = (items: string[], emptyLabel = '-') => {
if (!items || items.length === 0) {
return {emptyLabel};
}
@@ -112,11 +119,18 @@ export default function Content() {
{content.map((item) => {
const isExpanded = expandedId === item.id;
- return (
+ const secondaryKeywords = getList(
+ item.secondary_keywords,
+ item.metadata?.secondary_keywords
+ );
+ const tags = getList(item.tags, item.metadata?.tags);
+ const categories = getList(item.categories, item.metadata?.categories);
+
+ return (
|
- {item.meta_title || item.title || `Task #${item.task}`}
+ {item.meta_title || item.title || item.task_title || `Task #${item.task}`}
{item.meta_description && (
@@ -134,13 +148,13 @@ export default function Content() {
)}
|
- {renderBadgeList(item.secondary_keywords)}
+ {renderBadgeList(secondaryKeywords)}
|
- {renderBadgeList(item.tags)}
+ {renderBadgeList(tags)}
|
- {renderBadgeList(item.categories)}
+ {renderBadgeList(categories)}
|
{item.word_count?.toLocaleString?.() ?? '-'}
|